xref: /petsc/src/dm/impls/plex/plex.c (revision 21027e53faba6bd39309cdbce954e955b85b9619)
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;
14708be2fdSJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets;
15552f7358SJed Brown 
165a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
17552f7358SJed Brown 
18e5337592SStefano Zampini /*@
199318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
209318fe57SMatthew G. Knepley 
219318fe57SMatthew G. Knepley   Input Parameter:
22a1cb98faSBarry Smith . dm      - The `DMPLEX` object
239318fe57SMatthew G. Knepley 
249318fe57SMatthew G. Knepley   Output Parameter:
259318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
269318fe57SMatthew G. Knepley 
279318fe57SMatthew G. Knepley   Level: intermediate
289318fe57SMatthew G. Knepley 
29a1cb98faSBarry Smith   Note:
30a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
31a1cb98faSBarry Smith   If the mesh has no cells, this returns `PETSC_FALSE`.
32a1cb98faSBarry Smith 
331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
349318fe57SMatthew G. Knepley @*/
35d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
36d71ae5a4SJacob Faibussowitsch {
379318fe57SMatthew G. Knepley   DMPolytopeType ct;
389318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
399318fe57SMatthew G. Knepley 
409318fe57SMatthew G. Knepley   PetscFunctionBegin;
419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
429371c9d4SSatish Balay   if (cEnd <= cStart) {
439371c9d4SSatish Balay     *simplex = PETSC_FALSE;
443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
459371c9d4SSatish Balay   }
469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
479318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
499318fe57SMatthew G. Knepley }
509318fe57SMatthew G. Knepley 
519318fe57SMatthew G. Knepley /*@
52412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
53e5337592SStefano Zampini 
54d8d19677SJose E. Roman   Input Parameters:
55a1cb98faSBarry Smith + dm     - The `DMPLEX` object
56412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
57e5337592SStefano Zampini 
58e5337592SStefano Zampini   Output Parameters:
59412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
60412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
61e5337592SStefano Zampini 
62412e9a14SMatthew G. Knepley   Level: developer
63e5337592SStefano Zampini 
64a1cb98faSBarry Smith   Note:
65a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
66a1cb98faSBarry Smith 
671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
68e5337592SStefano Zampini @*/
69d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
70d71ae5a4SJacob Faibussowitsch {
71412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
72412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
73e5337592SStefano Zampini 
74e5337592SStefano Zampini   PetscFunctionBegin;
759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
76412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
77412e9a14SMatthew G. Knepley     DMPolytopeType cct;
78412e9a14SMatthew G. Knepley 
799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &cct));
80412e9a14SMatthew G. Knepley     if ((PetscInt)cct < 0) break;
81412e9a14SMatthew G. Knepley     switch (cct) {
82ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
83ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
84ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
85ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
86ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
87d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_HEXAHEDRON:
88d71ae5a4SJacob Faibussowitsch       ct = cct;
89d71ae5a4SJacob Faibussowitsch       break;
90d71ae5a4SJacob Faibussowitsch     default:
91d71ae5a4SJacob Faibussowitsch       break;
92e5337592SStefano Zampini     }
93412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
94e5337592SStefano Zampini   }
95412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
96412e9a14SMatthew G. Knepley     DMLabel ctLabel;
97412e9a14SMatthew G. Knepley 
989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
999566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE));
100695799ffSMatthew G. Knepley     // Reset label for fast lookup
101695799ffSMatthew G. Knepley     PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
102e5337592SStefano Zampini   }
103412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
104412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
1053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106e5337592SStefano Zampini }
107e5337592SStefano Zampini 
108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
109d71ae5a4SJacob Faibussowitsch {
110412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
111a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
1127e42fee7SMatthew G. Knepley 
1137e42fee7SMatthew G. Knepley   PetscFunctionBegin;
114e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
1159566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1197e42fee7SMatthew G. Knepley   if (field >= 0) {
1209566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1219566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1227e42fee7SMatthew G. Knepley   } else {
1239566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
1249566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
1257e42fee7SMatthew G. Knepley   }
126712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
127a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1287e42fee7SMatthew G. Knepley     *sStart = vStart;
1297e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
130f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1317e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
132a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1337e42fee7SMatthew G. Knepley     *sStart = cStart;
1347e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
135f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1367e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
137e630c359SToby Isaac   } else {
138e630c359SToby Isaac     if (field >= 0) {
139e630c359SToby Isaac       const char *fieldname;
140e630c359SToby Isaac 
1419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
14263a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
143e630c359SToby Isaac     } else {
14463a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
145e630c359SToby Isaac     }
146e630c359SToby Isaac   }
1473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1487e42fee7SMatthew G. Knepley }
1497e42fee7SMatthew G. Knepley 
1506913077dSMatthew G. Knepley /*@
1516913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
1526913077dSMatthew G. Knepley 
15320f4b53cSBarry Smith   Collective
1546913077dSMatthew G. Knepley 
1556913077dSMatthew G. Knepley   Input Parameters:
156a1cb98faSBarry Smith + dm - The `DMPLEX` object
1576913077dSMatthew G. Knepley . n  - The number of vectors
1586913077dSMatthew G. Knepley . u  - The array of local vectors
159a1cb98faSBarry Smith - viewer - The `PetscViewer`
1606913077dSMatthew G. Knepley 
1616913077dSMatthew G. Knepley   Level: advanced
1626913077dSMatthew G. Knepley 
1631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
1646913077dSMatthew G. Knepley @*/
165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
166d71ae5a4SJacob Faibussowitsch {
1676913077dSMatthew G. Knepley   PetscDS            ds;
1686913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
1696913077dSMatthew G. Knepley   PetscDrawLG        lg;
1706913077dSMatthew G. Knepley   Vec                coordinates;
1716913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
1726913077dSMatthew G. Knepley   PetscReal         *vals;
1736913077dSMatthew G. Knepley   PetscInt          *Nc;
1746913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
1756913077dSMatthew G. Knepley   char             **names;
1766913077dSMatthew G. Knepley 
1776913077dSMatthew G. Knepley   PetscFunctionBegin;
1789566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
1799566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
1809566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
1819566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
1826913077dSMatthew G. Knepley 
1839566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1843ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
1859566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
1866913077dSMatthew G. Knepley 
1879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
1886913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
1896913077dSMatthew G. Knepley     const char *vname;
1906913077dSMatthew G. Knepley 
1919566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
1926913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
1936913077dSMatthew G. Knepley       PetscObject disc;
1946913077dSMatthew G. Knepley       const char *fname;
1956913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
1966913077dSMatthew G. Knepley 
1979566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
1986913077dSMatthew G. Knepley       /* TODO Create names for components */
1996913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
2009566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
201c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
202c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
203c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
2049566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
2056913077dSMatthew G. Knepley       }
2066913077dSMatthew G. Knepley     }
2076913077dSMatthew G. Knepley   }
2089566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
2096913077dSMatthew G. Knepley   /* Just add P_1 support for now */
2109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2129566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
2139566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
2146913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2156913077dSMatthew G. Knepley     PetscScalar *x, *svals;
2166913077dSMatthew G. Knepley 
2179566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
2186913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
2199566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
2206913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
2216913077dSMatthew G. Knepley     }
2229566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
2236913077dSMatthew G. Knepley   }
2249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2259566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
2269566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
2279566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
2286913077dSMatthew G. Knepley 
2299566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
2309566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
2313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2326913077dSMatthew G. Knepley }
2336913077dSMatthew G. Knepley 
234d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
235d71ae5a4SJacob Faibussowitsch {
2366913077dSMatthew G. Knepley   DM dm;
2376913077dSMatthew G. Knepley 
2386913077dSMatthew G. Knepley   PetscFunctionBegin;
2399566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
2409566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
2413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2426913077dSMatthew G. Knepley }
2436913077dSMatthew G. Knepley 
244d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
245d71ae5a4SJacob Faibussowitsch {
246e412dcbdSMatthew G. Knepley   DM                 dm;
247d1df6f1dSMatthew G. Knepley   PetscSection       s;
248e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
249e412dcbdSMatthew G. Knepley   DM                 cdm;
250e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
251e412dcbdSMatthew G. Knepley   Vec                coordinates;
252c9c77995SMatthew G. Knepley   const PetscScalar *array;
253c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
254339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
2556913077dSMatthew G. Knepley   PetscBool          flg;
256d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
257e412dcbdSMatthew G. Knepley   const char        *name;
258339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
259e412dcbdSMatthew G. Knepley 
260e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
2619566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2629566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
2639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
2649566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
2659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
2669566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
2679566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
2689566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
2699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
272e412dcbdSMatthew G. Knepley 
2739566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
2749566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
275e412dcbdSMatthew G. Knepley 
2769566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
277c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
2789566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
279e412dcbdSMatthew G. Knepley 
280d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
281d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
282d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
283d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
284d1df6f1dSMatthew G. Knepley     IS          fis;
285d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
286d1df6f1dSMatthew G. Knepley     const char *fname;
287d1df6f1dSMatthew G. Knepley 
2889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
290d1df6f1dSMatthew G. Knepley 
2919566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
292ad540459SPierre Jolivet     else prefix[0] = '\0';
293d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
2949566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
2959566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
2969566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
2979566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
298d1df6f1dSMatthew G. Knepley     }
299d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
300d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
301d1df6f1dSMatthew G. Knepley 
3029566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
30363a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
30463a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
3059566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
306d1df6f1dSMatthew G. Knepley 
307d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3089566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
309339e3443SMatthew G. Knepley       if (!flg) {
3109566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
3119566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
312d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
313339e3443SMatthew G. Knepley       }
314c9c77995SMatthew G. Knepley 
3159566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
3169566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
317c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
3189566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
319e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
32099a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
321c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
322c9c77995SMatthew G. Knepley         PetscBool          isDG;
323e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
324e412dcbdSMatthew G. Knepley 
3259566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
326339e3443SMatthew G. Knepley         if (a) {
327d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
328339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
329339e3443SMatthew G. Knepley         } else {
330339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
331339e3443SMatthew G. Knepley           PetscInt     numVals, va;
332339e3443SMatthew G. Knepley 
3339566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
33463a3b9bcSJacob 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);
335d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
336d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
337d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
338d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
339339e3443SMatthew G. Knepley             break;
340d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
341d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
342d1df6f1dSMatthew 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]);
343d1df6f1dSMatthew G. Knepley             break;
344d71ae5a4SJacob Faibussowitsch           default:
345d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
346339e3443SMatthew G. Knepley           }
3479566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
348339e3443SMatthew G. Knepley         }
349c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
350e412dcbdSMatthew G. Knepley         switch (numCoords) {
351e412dcbdSMatthew G. Knepley         case 6:
3529edc3542SMatthew Knepley         case 12: /* Localized triangle */
3539566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
354e412dcbdSMatthew G. Knepley           break;
355e412dcbdSMatthew G. Knepley         case 8:
3569edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
3579566063dSJacob 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]));
3589566063dSJacob 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]));
359e412dcbdSMatthew G. Knepley           break;
360d71ae5a4SJacob Faibussowitsch         default:
361d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
362e412dcbdSMatthew G. Knepley         }
363c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
364e412dcbdSMatthew G. Knepley       }
3659566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
3669566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
3679566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
3689566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
369d1df6f1dSMatthew G. Knepley     }
370d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3719566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
3729566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
3739566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
374d1df6f1dSMatthew G. Knepley     }
375d1df6f1dSMatthew G. Knepley   }
3763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377e412dcbdSMatthew G. Knepley }
378e412dcbdSMatthew G. Knepley 
379d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
380d71ae5a4SJacob Faibussowitsch {
3816913077dSMatthew G. Knepley   DM        dm;
3826913077dSMatthew G. Knepley   PetscDraw draw;
3836913077dSMatthew G. Knepley   PetscInt  dim;
3846913077dSMatthew G. Knepley   PetscBool isnull;
3856913077dSMatthew G. Knepley 
3866913077dSMatthew G. Knepley   PetscFunctionBegin;
3879566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3889566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
3893ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
3906913077dSMatthew G. Knepley 
3919566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3929566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3936913077dSMatthew G. Knepley   switch (dim) {
394d71ae5a4SJacob Faibussowitsch   case 1:
395d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
396d71ae5a4SJacob Faibussowitsch     break;
397d71ae5a4SJacob Faibussowitsch   case 2:
398d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
399d71ae5a4SJacob Faibussowitsch     break;
400d71ae5a4SJacob Faibussowitsch   default:
401d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
4026913077dSMatthew G. Knepley   }
4033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4046913077dSMatthew G. Knepley }
4056913077dSMatthew G. Knepley 
406d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
407d71ae5a4SJacob Faibussowitsch {
408684b87d9SLisandro Dalcin   DM                      dm;
409684b87d9SLisandro Dalcin   Vec                     locv;
410684b87d9SLisandro Dalcin   const char             *name;
411684b87d9SLisandro Dalcin   PetscSection            section;
412684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
413e630c359SToby Isaac   PetscInt                numFields;
414684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
415684b87d9SLisandro Dalcin 
416684b87d9SLisandro Dalcin   PetscFunctionBegin;
4179566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4189566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
4209566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
4219566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4229566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
424e630c359SToby Isaac   if (!numFields) {
4259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4269566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
427e630c359SToby Isaac   } else {
428e630c359SToby Isaac     PetscInt f;
429e630c359SToby Isaac 
430e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4319566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
432e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4339566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4349566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
435e630c359SToby Isaac     }
4369566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
437e630c359SToby Isaac   }
4383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
439684b87d9SLisandro Dalcin }
440684b87d9SLisandro Dalcin 
441d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
442d71ae5a4SJacob Faibussowitsch {
443552f7358SJed Brown   DM        dm;
4445f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
445552f7358SJed Brown 
446552f7358SJed Brown   PetscFunctionBegin;
4479566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
44828b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
4509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
4519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
4529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
4535f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
4545f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
455684b87d9SLisandro Dalcin     PetscInt    i, numFields;
456684b87d9SLisandro Dalcin     PetscObject fe;
457ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
458684b87d9SLisandro Dalcin     Vec         locv = v;
459684b87d9SLisandro Dalcin     const char *name;
460684b87d9SLisandro Dalcin     PetscInt    step;
461684b87d9SLisandro Dalcin     PetscReal   time;
462ef31f671SMatthew G. Knepley 
4639566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
464684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
4659566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
4669371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
4679371c9d4SSatish Balay         fem = PETSC_TRUE;
4689371c9d4SSatish Balay         break;
4699371c9d4SSatish Balay       }
470ef31f671SMatthew G. Knepley     }
471684b87d9SLisandro Dalcin     if (fem) {
472798534f6SMatthew G. Knepley       PetscObject isZero;
473798534f6SMatthew G. Knepley 
4749566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4759566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
4769566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
4779566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
4789566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
4799566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4809566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4819566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
482ef31f671SMatthew G. Knepley     }
483552f7358SJed Brown     if (isvtk) {
4849566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
485b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
486b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4879566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
488b136c2c9SMatthew G. Knepley #else
489b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
490b136c2c9SMatthew G. Knepley #endif
491f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4929566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
493684b87d9SLisandro Dalcin     } else if (isglvis) {
4949566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
4959566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
4969566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
4975f34f2dcSJed Brown     } else if (iscgns) {
4985f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
4995f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
5005f34f2dcSJed Brown #else
5015f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
5025f34f2dcSJed Brown #endif
503684b87d9SLisandro Dalcin     }
504798534f6SMatthew G. Knepley     if (fem) {
5059566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5069566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
507798534f6SMatthew G. Knepley     }
508552f7358SJed Brown   } else {
509684b87d9SLisandro Dalcin     PetscBool isseq;
510684b87d9SLisandro Dalcin 
5119566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5129566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5139566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
514552f7358SJed Brown   }
5153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
516552f7358SJed Brown }
517552f7358SJed Brown 
518d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
519d71ae5a4SJacob Faibussowitsch {
520552f7358SJed Brown   DM        dm;
5215f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
522552f7358SJed Brown 
523552f7358SJed Brown   PetscFunctionBegin;
5249566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
52528b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5305f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
5325f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
533552f7358SJed Brown     Vec         locv;
534798534f6SMatthew G. Knepley     PetscObject isZero;
535552f7358SJed Brown     const char *name;
536552f7358SJed Brown 
5379566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
5399566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
5409566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5419566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5429566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5439566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5449566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5459566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5469566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
547b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
548b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5499566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
550b136c2c9SMatthew G. Knepley #else
551b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
552b136c2c9SMatthew G. Knepley #endif
5536823f3c5SBlaise Bourdin   } else if (isexodusii) {
5546823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5559566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5566823f3c5SBlaise Bourdin #else
5576823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5586823f3c5SBlaise Bourdin #endif
559552f7358SJed Brown   } else {
560684b87d9SLisandro Dalcin     PetscBool isseq;
561684b87d9SLisandro Dalcin 
5629566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5639566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5649566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
565552f7358SJed Brown   }
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
567552f7358SJed Brown }
568552f7358SJed Brown 
569d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
570d71ae5a4SJacob Faibussowitsch {
571d930f514SMatthew G. Knepley   DM                dm;
572d930f514SMatthew G. Knepley   MPI_Comm          comm;
573d930f514SMatthew G. Knepley   PetscViewerFormat format;
574d930f514SMatthew G. Knepley   Vec               v;
575d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
576d930f514SMatthew G. Knepley 
577d930f514SMatthew G. Knepley   PetscFunctionBegin;
5789566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
58028b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5819566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
584d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
585a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
586a8ad634aSStefano Zampini     /* this need a better fix */
587a8ad634aSStefano Zampini     if (dm->useNatural) {
588a8ad634aSStefano Zampini       if (dm->sfNatural) {
589d930f514SMatthew G. Knepley         const char *vecname;
590d930f514SMatthew G. Knepley         PetscInt    n, nroots;
591d930f514SMatthew G. Knepley 
5929566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5939566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
594d930f514SMatthew G. Knepley         if (n == nroots) {
595f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
5969566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5979566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5989566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
5999566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
600d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
601d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
602a8ad634aSStefano Zampini     } else v = originalv;
603a8ad634aSStefano Zampini   } else v = originalv;
604a8ad634aSStefano Zampini 
605d930f514SMatthew G. Knepley   if (ishdf5) {
606d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6079566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
608d930f514SMatthew G. Knepley #else
609d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
610d930f514SMatthew G. Knepley #endif
611d930f514SMatthew G. Knepley   } else if (isvtk) {
612d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
613d930f514SMatthew G. Knepley   } else {
614d930f514SMatthew G. Knepley     PetscBool isseq;
615d930f514SMatthew G. Knepley 
6169566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6179566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6189566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
619d930f514SMatthew G. Knepley   }
620f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
6213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
622d930f514SMatthew G. Knepley }
623d930f514SMatthew G. Knepley 
624d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
625d71ae5a4SJacob Faibussowitsch {
6262c40f234SMatthew G. Knepley   DM        dm;
6272c40f234SMatthew G. Knepley   PetscBool ishdf5;
6282c40f234SMatthew G. Knepley 
6292c40f234SMatthew G. Knepley   PetscFunctionBegin;
6309566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6332c40f234SMatthew G. Knepley   if (ishdf5) {
6342c40f234SMatthew G. Knepley     DM          dmBC;
6352c40f234SMatthew G. Knepley     Vec         gv;
6362c40f234SMatthew G. Knepley     const char *name;
6372c40f234SMatthew G. Knepley 
6389566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6399566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6409566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6419566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
6429566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6439566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6449566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6459566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6461baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6482c40f234SMatthew G. Knepley }
6492c40f234SMatthew G. Knepley 
650d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
651d71ae5a4SJacob Faibussowitsch {
6522c40f234SMatthew G. Knepley   DM        dm;
6536823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
6542c40f234SMatthew G. Knepley 
6552c40f234SMatthew G. Knepley   PetscFunctionBegin;
6569566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
65728b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6602c40f234SMatthew G. Knepley   if (ishdf5) {
661878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6629566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
663b136c2c9SMatthew G. Knepley #else
664b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
665878b459fSMatthew G. Knepley #endif
6666823f3c5SBlaise Bourdin   } else if (isexodusii) {
6676823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6689566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6696823f3c5SBlaise Bourdin #else
6706823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6716823f3c5SBlaise Bourdin #endif
6721baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
674552f7358SJed Brown }
675552f7358SJed Brown 
676d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
677d71ae5a4SJacob Faibussowitsch {
678d930f514SMatthew G. Knepley   DM                dm;
679d930f514SMatthew G. Knepley   PetscViewerFormat format;
680d930f514SMatthew G. Knepley   PetscBool         ishdf5;
681d930f514SMatthew G. Knepley 
682d930f514SMatthew G. Knepley   PetscFunctionBegin;
6839566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
68428b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6859566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
687d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
688a8ad634aSStefano Zampini     if (dm->useNatural) {
689d930f514SMatthew G. Knepley       if (dm->sfNatural) {
690d930f514SMatthew G. Knepley         if (ishdf5) {
691d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
692d930f514SMatthew G. Knepley           Vec         v;
693d930f514SMatthew G. Knepley           const char *vecname;
694d930f514SMatthew G. Knepley 
695f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
6969566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
6979566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
6989566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6999566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
7009566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
701f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
702d930f514SMatthew G. Knepley #else
703d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
704d930f514SMatthew G. Knepley #endif
705d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
706d930f514SMatthew G. Knepley       }
7071baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
708d930f514SMatthew G. Knepley   }
7093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
710d930f514SMatthew G. Knepley }
711d930f514SMatthew G. Knepley 
712d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
713d71ae5a4SJacob Faibussowitsch {
714731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
715731e8ddeSMatthew G. Knepley   Vec                coordinates;
716ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
717731e8ddeSMatthew G. Knepley   const char        *name[4];
718731e8ddeSMatthew G. Knepley   const PetscScalar *a;
719731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
720731e8ddeSMatthew G. Knepley 
721731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7239566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7249566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7299566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
730731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
731731e8ddeSMatthew G. Knepley   name[1]       = "edge";
732731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
733731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
734731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
735731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
736ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
737731e8ddeSMatthew G. Knepley 
7389566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
73963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
742731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
743731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
744731e8ddeSMatthew G. Knepley 
745731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
747731e8ddeSMatthew G. Knepley       if (!dof) continue;
7489566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
75063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
751731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
7529566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
753731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7549566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7559566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
756731e8ddeSMatthew G. Knepley         }
7579566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
758731e8ddeSMatthew G. Knepley       }
7599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
760731e8ddeSMatthew G. Knepley     }
7619566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
763731e8ddeSMatthew G. Knepley   }
7649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
7653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
766731e8ddeSMatthew G. Knepley }
767731e8ddeSMatthew G. Knepley 
7689371c9d4SSatish Balay typedef enum {
7699371c9d4SSatish Balay   CS_CARTESIAN,
7709371c9d4SSatish Balay   CS_POLAR,
7719371c9d4SSatish Balay   CS_CYLINDRICAL,
7729371c9d4SSatish Balay   CS_SPHERICAL
7739371c9d4SSatish Balay } CoordSystem;
77419ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
77519ad8254SMatthew G. Knepley 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
777d71ae5a4SJacob Faibussowitsch {
77819ad8254SMatthew G. Knepley   PetscInt i;
77919ad8254SMatthew G. Knepley 
78019ad8254SMatthew G. Knepley   PetscFunctionBegin;
78119ad8254SMatthew G. Knepley   if (dim > 3) {
7829566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
78319ad8254SMatthew G. Knepley   } else {
784bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
78519ad8254SMatthew G. Knepley 
78619ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
78719ad8254SMatthew G. Knepley     switch (cs) {
7889371c9d4SSatish Balay     case CS_CARTESIAN:
7899371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
7909371c9d4SSatish Balay       break;
79119ad8254SMatthew G. Knepley     case CS_POLAR:
79263a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
79319ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
79419ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
79519ad8254SMatthew G. Knepley       break;
79619ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
79763a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
79819ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
79919ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
80019ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
80119ad8254SMatthew G. Knepley       break;
80219ad8254SMatthew G. Knepley     case CS_SPHERICAL:
80363a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
80419ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
80519ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
80619ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
80719ad8254SMatthew G. Knepley       break;
80819ad8254SMatthew G. Knepley     }
8099566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
81019ad8254SMatthew G. Knepley   }
8113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81219ad8254SMatthew G. Knepley }
81319ad8254SMatthew G. Knepley 
814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
815d71ae5a4SJacob Faibussowitsch {
816552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
8176858538eSMatthew G. Knepley   DM                cdm, cdmCell;
8186858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
8196858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
820552f7358SJed Brown   PetscViewerFormat format;
821552f7358SJed Brown 
822552f7358SJed Brown   PetscFunctionBegin;
8239566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
824552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
825552f7358SJed Brown     const char *name;
826f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8279318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
828552f7358SJed Brown     PetscMPIInt rank, size;
829552f7358SJed Brown 
8309f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
8319f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
8329f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8339f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
8349f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
8359f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
8369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
8399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8419566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
84363a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
84463a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
84563a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
84663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
84863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
849552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
850552f7358SJed Brown       PetscInt dof, off, s;
851552f7358SJed Brown 
8529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
85448a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
855552f7358SJed Brown     }
8569566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
85763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
85863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
859552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
860552f7358SJed Brown       PetscInt dof, off, c;
861552f7358SJed Brown 
8629566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
86448a46eb9SPierre 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]));
865552f7358SJed Brown     }
8669566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8683d2e540fSStefano Zampini     if (coordSection && coordinates) {
86919ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8706858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8716858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
87219ad8254SMatthew G. Knepley       PetscMPIInt        rank;
87319ad8254SMatthew G. Knepley       const char        *name;
87419ad8254SMatthew G. Knepley 
8759566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
8769566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
87863a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8806858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8816858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8826858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
8836858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
8849566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
88563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
88663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
8879566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
88819ad8254SMatthew G. Knepley 
8899566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8906858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
8919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
89319ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
89419ad8254SMatthew G. Knepley         PetscInt dof, off;
89519ad8254SMatthew G. Knepley 
8966858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
8979566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
8989566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
8996858538eSMatthew G. Knepley           if (dof) {
90063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
9019566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
9029566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
90319ad8254SMatthew G. Knepley           }
9046858538eSMatthew G. Knepley         }
9056858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
9066858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
9076858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
9086858538eSMatthew G. Knepley           if (dof) {
9096858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
9106858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
9116858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
9126858538eSMatthew G. Knepley           }
9136858538eSMatthew G. Knepley         }
9146858538eSMatthew G. Knepley       }
9159566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
9169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9179566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
9186858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
9193d2e540fSStefano Zampini     }
9209566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9219566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
9229318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
9239318fe57SMatthew G. Knepley       DMLabel     label;
9249318fe57SMatthew G. Knepley       PetscBool   isdepth;
9259318fe57SMatthew G. Knepley       const char *name;
9269318fe57SMatthew G. Knepley 
9279566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9289566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9299318fe57SMatthew G. Knepley       if (isdepth) continue;
9309566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9319566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9329318fe57SMatthew G. Knepley     }
933552f7358SJed Brown     if (size > 1) {
934552f7358SJed Brown       PetscSF sf;
935552f7358SJed Brown 
9369566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9379566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
938552f7358SJed Brown     }
9394e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
9409566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
941552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9420588280cSMatthew G. Knepley     const char  *name, *color;
9430588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9440588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
945fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
946552f7358SJed Brown     PetscReal    scale      = 2.0;
94778081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
948b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9490588280cSMatthew G. Knepley     double       tcoords[3];
950552f7358SJed Brown     PetscScalar *coords;
951b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
952552f7358SJed Brown     PetscMPIInt  rank, size;
9530588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
954b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
955fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
956fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
957552f7358SJed Brown 
9589f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9599f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9609f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9619f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9629f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9639f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9649566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9669566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9670588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9680588280cSMatthew G. Knepley     numColors  = 10;
9690588280cSMatthew G. Knepley     numLColors = 10;
9709566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
974b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
975b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
976b7f6ffafSMatthew G. Knepley     n = 4;
9779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9781dca8a05SBarry 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);
9799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9801dca8a05SBarry 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);
9819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9820588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9840588280cSMatthew G. Knepley     if (!useColors) {
9850588280cSMatthew G. Knepley       numColors = 3;
9869566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9870588280cSMatthew G. Knepley     }
9889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9890588280cSMatthew G. Knepley     if (!useColors) {
9900588280cSMatthew G. Knepley       numLColors = 4;
9919566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9920588280cSMatthew G. Knepley     }
9939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
994b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
9959566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
9961dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
997202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
9989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
999fe1cc32dSStefano Zampini 
1000fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
10019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
10029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
10039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
10049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1005fe1cc32dSStefano Zampini     if (lflg) {
1006fe1cc32dSStefano Zampini       DMLabel lbl;
1007fe1cc32dSStefano Zampini 
10089566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1009fe1cc32dSStefano Zampini       if (lbl) {
1010fe1cc32dSStefano Zampini         PetscInt val, defval;
1011fe1cc32dSStefano Zampini 
10129566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
10139566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1014fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1015fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1016fe1cc32dSStefano Zampini           PetscInt  closureSize;
1017fe1cc32dSStefano Zampini 
10189566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1019fe1cc32dSStefano Zampini           if (val == defval) continue;
1020fe1cc32dSStefano Zampini 
10219566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
102248a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
10239566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1024fe1cc32dSStefano Zampini         }
1025fe1cc32dSStefano Zampini       }
1026fe1cc32dSStefano Zampini     }
1027fe1cc32dSStefano Zampini 
10289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10309566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
10319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10320588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1033552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1034552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1035552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10365f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10370588280cSMatthew G. Knepley     if (size > 1) {
10389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1039770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
104063a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
104163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1042770b213bSMatthew G Knepley       }
10439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10440588280cSMatthew G. Knepley     }
1045b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1046b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1047b7f6ffafSMatthew G. Knepley 
104863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
104963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
105063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
10519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
105263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
105363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
10549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
105563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
105663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
105763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
105863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
10599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1060b7f6ffafSMatthew G. Knepley     }
10619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1062fe1cc32dSStefano Zampini 
1063552f7358SJed Brown     /* Plot vertices */
10649566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1066552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1067552f7358SJed Brown       PetscInt  off, dof, d;
10680588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1069552f7358SJed Brown 
1070fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
10719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
107463a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
10750588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10760588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1077c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10780588280cSMatthew G. Knepley       }
10790588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10809371c9d4SSatish Balay       if (dim == 3) {
10819371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
10829371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
10839371c9d4SSatish Balay         tcoords[2]    = -tmp;
10849371c9d4SSatish Balay       }
1085552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10869566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10879566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1088552f7358SJed Brown       }
1089b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1090b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
10910588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10920588280cSMatthew G. Knepley         PetscInt val;
10939566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10949371c9d4SSatish Balay         if (val >= 0) {
10959371c9d4SSatish Balay           color     = lcolors[l % numLColors];
10969371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
10979371c9d4SSatish Balay           break;
10989371c9d4SSatish Balay         }
10990588280cSMatthew G. Knepley       }
1100b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
110163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1102b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
110363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
11041baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1105552f7358SJed Brown     }
11069566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
11079566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1108b7f6ffafSMatthew G. Knepley     /* Plot edges */
1109b7f6ffafSMatthew G. Knepley     if (plotEdges) {
11109566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
11119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1112b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1113b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1114b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1115b7f6ffafSMatthew G. Knepley 
1116b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
11179566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
111863a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
11199566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
11209566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
11219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
11229566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
11239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1124b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1125b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1126b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1127b7f6ffafSMatthew G. Knepley         }
1128b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
11299371c9d4SSatish Balay         if (dim == 3) {
11309371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
11319371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
11329371c9d4SSatish Balay           tcoords[2]    = -tmp;
11339371c9d4SSatish Balay         }
1134b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11359566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11369566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1137b7f6ffafSMatthew G. Knepley         }
1138b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1139b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1140b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1141b7f6ffafSMatthew G. Knepley           PetscInt val;
11429566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
11439371c9d4SSatish Balay           if (val >= 0) {
11449371c9d4SSatish Balay             color = lcolors[l % numLColors];
11459371c9d4SSatish Balay             break;
11469371c9d4SSatish Balay           }
1147b7f6ffafSMatthew G. Knepley         }
114863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1149b7f6ffafSMatthew G. Knepley       }
11509566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11519566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1153b7f6ffafSMatthew G. Knepley     }
1154846a3e8bSMatthew G. Knepley     /* Plot cells */
1155b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1156846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1157846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1158846a3e8bSMatthew G. Knepley 
1159fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1160846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1161846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1162846a3e8bSMatthew G. Knepley           PetscInt val;
11639566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
11649371c9d4SSatish Balay           if (val >= 0) {
11659371c9d4SSatish Balay             color = lcolors[l % numLColors];
11669371c9d4SSatish Balay             break;
11679371c9d4SSatish Balay           }
1168846a3e8bSMatthew G. Knepley         }
11699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
117063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1171846a3e8bSMatthew G. Knepley       }
1172846a3e8bSMatthew G. Knepley     } else {
1173b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1174846a3e8bSMatthew G. Knepley 
1175b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1176b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1177fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11789566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
11799371c9d4SSatish Balay         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1180b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1181b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1182b7f6ffafSMatthew G. Knepley 
11839566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11849566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1185b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1186b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1187b7f6ffafSMatthew G. Knepley 
11889566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
118963a3b9bcSJacob 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));
1190b7f6ffafSMatthew G. Knepley           }
1191b7f6ffafSMatthew G. Knepley         } else {
1192b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1193b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1194b7f6ffafSMatthew G. Knepley 
11959566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1196846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1197846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1198846a3e8bSMatthew G. Knepley 
1199b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1200846a3e8bSMatthew G. Knepley           }
12019566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1202b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1203b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1204b7f6ffafSMatthew G. Knepley 
1205b7f6ffafSMatthew G. Knepley             if (v > 0) {
1206b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1207b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1208b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1209b7f6ffafSMatthew G. Knepley 
12109371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
12119371c9d4SSatish Balay                 endpoints[1] = vertex;
12129566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
121363a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
121463a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
12159566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
12161baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1217b7f6ffafSMatthew G. Knepley             }
121863a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1219b7f6ffafSMatthew G. Knepley           }
12209566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
12219566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1222846a3e8bSMatthew G. Knepley         }
1223846a3e8bSMatthew G. Knepley       }
1224b7f6ffafSMatthew G. Knepley     }
1225846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1226846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1227846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1228c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1229c713ec31SMatthew G. Knepley       const PetscScalar *array;
1230c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1231c713ec31SMatthew G. Knepley       PetscBool          isDG;
1232846a3e8bSMatthew G. Knepley 
1233fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1234c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1235c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1236c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
12379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1238c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1239c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1240c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1241846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1242846a3e8bSMatthew G. Knepley         }
1243846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12449371c9d4SSatish Balay         if (cdim == 3) {
12459371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12469371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12479371c9d4SSatish Balay           tcoords[2]    = -tmp;
12489371c9d4SSatish Balay         }
1249ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1250846a3e8bSMatthew G. Knepley       }
1251ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1252c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1253c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
12549566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12559566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1256846a3e8bSMatthew G. Knepley       }
1257b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1258b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1259846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1260846a3e8bSMatthew G. Knepley         PetscInt val;
12619566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
12629371c9d4SSatish Balay         if (val >= 0) {
12639371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12649371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12659371c9d4SSatish Balay           break;
12669371c9d4SSatish Balay         }
1267846a3e8bSMatthew G. Knepley       }
1268b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
126963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1270b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
127163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12721baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1273846a3e8bSMatthew G. Knepley     }
1274b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1275b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
12769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12789566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1281552f7358SJed Brown 
1282b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
12839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1288b7f6ffafSMatthew G. Knepley 
1289b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
12909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1295b7f6ffafSMatthew G. Knepley 
1296b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1297b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1298b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1299b7f6ffafSMatthew G. Knepley 
13009566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
13019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
130248a46eb9SPierre 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));
13030588280cSMatthew G. Knepley       }
13040588280cSMatthew G. Knepley     }
13059566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
13069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
13079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
130863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
13099566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
13109566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
13119566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
13129566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
13139566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
13140f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
13150f7d6e4aSStefano Zampini     Vec                    cown, acown;
13160f7d6e4aSStefano Zampini     VecScatter             sct;
13170f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
13180f7d6e4aSStefano Zampini     IS                     gid, acis;
13190f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
13200f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
13210f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
13220f7d6e4aSStefano Zampini     const PetscInt        *idxs;
13230f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
13240f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
13250f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
13260f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
13270f7d6e4aSStefano Zampini 
13289566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
13299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1330b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
13319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
13320f7d6e4aSStefano Zampini #endif
13330f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
13349566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
13359566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
13360f7d6e4aSStefano Zampini       d1 = 0;
13379566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
13380f7d6e4aSStefano Zampini       nid = d2;
13399566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
13409566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
13419566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
13420f7d6e4aSStefano Zampini     } else nid = 0.0;
13430f7d6e4aSStefano Zampini 
13440f7d6e4aSStefano Zampini     /* Get connectivity */
13459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
13470f7d6e4aSStefano Zampini 
13480f7d6e4aSStefano Zampini     /* filter overlapped local cells */
13499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
13509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
13519566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
13529566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
13530f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13540f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
13550f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
13560f7d6e4aSStefano Zampini     }
13579566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
135863a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
13599566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13609566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
13610f7d6e4aSStefano Zampini 
13620f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13639566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
13649566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
13659566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
13669566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
13670f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13689566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
13699566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
13709566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13719566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13729566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13739566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13749566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13750f7d6e4aSStefano Zampini 
13760f7d6e4aSStefano Zampini     /* compute edgeCut */
13770f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
13789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
13799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
13809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
13819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13829566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
13830f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13840f7d6e4aSStefano Zampini       PetscInt totl;
13850f7d6e4aSStefano Zampini 
13860f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
13879566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
13880f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13890f7d6e4aSStefano Zampini         if (work[i] < 0) {
13900f7d6e4aSStefano Zampini           ect += 1;
13910f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13920f7d6e4aSStefano Zampini         }
13930f7d6e4aSStefano Zampini       }
13940f7d6e4aSStefano Zampini     }
13959566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
13969566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
13970f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
13980f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13991c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
140063a3b9bcSJacob 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]));
14010f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
14020f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
14030f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
14041c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
140563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1406b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
140763a3b9bcSJacob 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.));
14080f7d6e4aSStefano Zampini #else
140963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
14100f7d6e4aSStefano Zampini #endif
14119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
14129566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
14139566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
14149566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1415552f7358SJed Brown   } else {
1416412e9a14SMatthew G. Knepley     const char    *name;
1417d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1418412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1419d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1420ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
14219318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1422412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1423412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1424552f7358SJed Brown 
14259566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
14279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
14289566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
14299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14309566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
143163a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
143263a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
143363a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
14349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
14351c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
14369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1437d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
14389566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
14399566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1440412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1441412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1442412e9a14SMatthew G. Knepley 
14439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
14449566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1445412e9a14SMatthew G. Knepley       ict = ct0;
14469566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1447412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1448412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1449412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1450412e9a14SMatthew G. Knepley 
14519566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1452412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1453412e9a14SMatthew G. Knepley         else ++Nc[1];
1454412e9a14SMatthew G. Knepley       }
1455ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14569566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
14579566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14589566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
145963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1460834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1461dd400576SPatrick Sanan           if (rank == 0) {
146263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
146363a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
146463a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1465834065abSMatthew G. Knepley           }
1466cbb7f117SMark Adams         }
1467ca7bf7eeSMatthew G. Knepley       } else {
1468ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1469ca7bf7eeSMatthew G. Knepley 
14709371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
14719371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
14729566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
14739371c9d4SSatish Balay         locMinMax[0] = Nc[1];
14749371c9d4SSatish Balay         locMinMax[1] = Nc[1];
14759566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1476ca7bf7eeSMatthew G. Knepley         if (d == depth) {
14779371c9d4SSatish Balay           locMinMax[0] = gcNum;
14789371c9d4SSatish Balay           locMinMax[1] = gcNum;
14799566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1480ca7bf7eeSMatthew G. Knepley         }
148163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14829566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14839566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14849566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1485ca7bf7eeSMatthew G. Knepley       }
14869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1487552f7358SJed Brown     }
14889566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14899318fe57SMatthew G. Knepley     {
14909318fe57SMatthew G. Knepley       const PetscReal *maxCell;
14919318fe57SMatthew G. Knepley       const PetscReal *L;
14926858538eSMatthew G. Knepley       PetscBool        localized;
14939318fe57SMatthew G. Knepley 
14944fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
14959566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
14966858538eSMatthew G. Knepley       if (L || localized) {
14976858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
14989566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14996858538eSMatthew G. Knepley         if (L) {
15006858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
15019318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
15026858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
15036858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
15049318fe57SMatthew G. Knepley           }
15056858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
15066858538eSMatthew G. Knepley         }
15076858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
15089566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15099318fe57SMatthew G. Knepley       }
15109318fe57SMatthew G. Knepley     }
15119566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
15129566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1513a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1514a57dd577SMatthew G Knepley       DMLabel         label;
1515a57dd577SMatthew G Knepley       const char     *name;
1516a57dd577SMatthew G Knepley       IS              valueIS;
1517a57dd577SMatthew G Knepley       const PetscInt *values;
1518a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1519a57dd577SMatthew G Knepley 
15209566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
15219566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
15229566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
152363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
15249566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
15259566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
15269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1527a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1528a57dd577SMatthew G Knepley         PetscInt size;
1529a57dd577SMatthew G Knepley 
15309566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
15319566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
153263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1533a57dd577SMatthew G Knepley       }
15349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
15359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15369566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
15379566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1538a57dd577SMatthew G Knepley     }
1539c1cad2e7SMatthew G. Knepley     {
1540c1cad2e7SMatthew G. Knepley       char    **labelNames;
1541c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1542c1cad2e7SMatthew G. Knepley       PetscBool flg;
1543c1cad2e7SMatthew G. Knepley 
15449566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
15459566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1546c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1547c1cad2e7SMatthew G. Knepley         DMLabel label;
1548c1cad2e7SMatthew G. Knepley 
15499566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1550c1cad2e7SMatthew G. Knepley         if (flg) {
15519566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
15529566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1553c1cad2e7SMatthew G. Knepley         }
15549566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1555c1cad2e7SMatthew G. Knepley       }
15569566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1557c1cad2e7SMatthew G. Knepley     }
155834aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
155934aa8a36SMatthew G. Knepley     if (dm->Nf) {
156034aa8a36SMatthew G. Knepley       PetscInt f;
156134aa8a36SMatthew G. Knepley 
156234aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
156334aa8a36SMatthew G. Knepley         const char *name;
156434aa8a36SMatthew G. Knepley 
15659566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15669566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15679566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15689566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
156934aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15709566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15719566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
157234aa8a36SMatthew G. Knepley         } else {
15739566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15749566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
157534aa8a36SMatthew G. Knepley         }
15769566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
157734aa8a36SMatthew G. Knepley       }
157834aa8a36SMatthew G. Knepley     }
15799566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15808e7ff633SMatthew G. Knepley     if (cdm) {
15819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15829f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
15839566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15858e7ff633SMatthew G. Knepley     }
1586552f7358SJed Brown   }
15873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1588552f7358SJed Brown }
1589552f7358SJed Brown 
1590d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1591d71ae5a4SJacob Faibussowitsch {
1592e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1593e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1594a12d352dSMatthew G. Knepley   PetscInt       cdim;
1595e5c487bfSMatthew G. Knepley 
1596e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
15979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15989566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
15999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1600e5c487bfSMatthew G. Knepley   switch (ct) {
1601a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1602a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1603a12d352dSMatthew G. Knepley     switch (cdim) {
16049371c9d4SSatish Balay     case 1: {
1605a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1606a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1607a12d352dSMatthew G. Knepley 
16089566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
16099566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
16109566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
16119371c9d4SSatish Balay     } break;
16129371c9d4SSatish Balay     case 2: {
1613a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1614a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1615a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1616a12d352dSMatthew G. Knepley 
16179566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16189566063dSJacob 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));
16199566063dSJacob 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));
16209371c9d4SSatish Balay     } break;
1621d71ae5a4SJacob Faibussowitsch     default:
1622d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1623a12d352dSMatthew G. Knepley     }
1624a12d352dSMatthew G. Knepley     break;
1625e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
16269371c9d4SSatish 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));
16279566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16289566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16299566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1630e5c487bfSMatthew G. Knepley     break;
1631e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
16329371c9d4SSatish 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));
16339371c9d4SSatish 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));
16349566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16369566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16379566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1638e5c487bfSMatthew G. Knepley     break;
16399f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
16409f4ada15SMatthew 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));
16419f4ada15SMatthew 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));
16429f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16439f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16449f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16459f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
16469f4ada15SMatthew G. Knepley     break;
1647d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1648d71ae5a4SJacob Faibussowitsch     break;
1649d71ae5a4SJacob Faibussowitsch   default:
1650d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1651e5c487bfSMatthew G. Knepley   }
16523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1653e5c487bfSMatthew G. Knepley }
1654e5c487bfSMatthew G. Knepley 
1655d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1656d71ae5a4SJacob Faibussowitsch {
1657e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1658e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1659e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1660e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1661e5c487bfSMatthew G. Knepley 
1662e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
16649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1665e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1666e5c487bfSMatthew G. Knepley   switch (ct) {
16679371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
1668e5c487bfSMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1669e5c487bfSMatthew G. Knepley 
16709371c9d4SSatish Balay     for (v = 0; v < 3; ++v) {
16719371c9d4SSatish Balay       centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.;
16729371c9d4SSatish Balay       centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.;
16739371c9d4SSatish Balay     }
1674e5c487bfSMatthew G. Knepley     for (e = 0; e < 3; ++e) {
1675e5c487bfSMatthew G. Knepley       refCoords[0] = refVertices[e * 2 + 0];
1676e5c487bfSMatthew G. Knepley       refCoords[1] = refVertices[e * 2 + 1];
1677e5c487bfSMatthew G. Knepley       for (d = 1; d <= edgeDiv; ++d) {
1678e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv;
1679e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv;
1680e5c487bfSMatthew G. Knepley       }
16819566063dSJacob Faibussowitsch       PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1682e5c487bfSMatthew G. Knepley       for (d = 0; d < edgeDiv; ++d) {
16839566063dSJacob 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));
16849566063dSJacob 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));
1685e5c487bfSMatthew G. Knepley       }
1686e5c487bfSMatthew G. Knepley     }
16879371c9d4SSatish Balay   } break;
1688d71ae5a4SJacob Faibussowitsch   default:
1689d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1690e5c487bfSMatthew G. Knepley   }
16913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1692e5c487bfSMatthew G. Knepley }
1693e5c487bfSMatthew G. Knepley 
1694d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1695d71ae5a4SJacob Faibussowitsch {
1696e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1697e412dcbdSMatthew G. Knepley   DM           cdm;
1698e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1699e412dcbdSMatthew G. Knepley   Vec          coordinates;
1700c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1701e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1702e5c487bfSMatthew G. Knepley   PetscBool    isnull, drawAffine = PETSC_TRUE;
1703c9c77995SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, edgeDiv = 4;
1704e412dcbdSMatthew G. Knepley 
1705e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
17069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
170763a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
17089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
17099566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
17109566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
17119566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
17129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
17139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1715e412dcbdSMatthew G. Knepley 
17169566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
17179566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
17183ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
17199566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1720e412dcbdSMatthew G. Knepley 
1721c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
17229566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
17239566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1724e412dcbdSMatthew G. Knepley 
1725cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1726cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1727c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1728ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1729c9c77995SMatthew G. Knepley     PetscBool          isDG;
1730cf3064d3SMatthew G. Knepley 
1731c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
17321baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
17331baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1734c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1735cf3064d3SMatthew G. Knepley   }
17369566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
17379566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
17389566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
17399566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
17403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1741e412dcbdSMatthew G. Knepley }
1742e412dcbdSMatthew G. Knepley 
17431e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17441e50132fSMatthew G. Knepley   #include <exodusII.h>
17456823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
17461e50132fSMatthew G. Knepley #endif
17471e50132fSMatthew G. Knepley 
1748d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1749d71ae5a4SJacob Faibussowitsch {
17505f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1751002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1752552f7358SJed Brown 
1753552f7358SJed Brown   PetscFunctionBegin;
1754552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1755552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
17579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
17589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
17599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
17609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
17619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
17625f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1763552f7358SJed Brown   if (iascii) {
17648135c375SStefano Zampini     PetscViewerFormat format;
17659566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17661baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17671baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1768c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1769c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17709566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1771c6ccd67eSMatthew G. Knepley #else
1772c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1773552f7358SJed Brown #endif
1774e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17759566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1776e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17779566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17788135c375SStefano Zampini   } else if (isglvis) {
17799566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17801e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17811e50132fSMatthew G. Knepley   } else if (isexodus) {
17826823f3c5SBlaise Bourdin     /*
17836823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17846823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1785da81f932SPierre Jolivet       with ID 1, containing all cells.
17866823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
17876823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
17886823f3c5SBlaise Bourdin     */
17896823f3c5SBlaise Bourdin     PetscInt numCS;
17909566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
17916823f3c5SBlaise Bourdin     if (!numCS) {
17921e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17939566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
17949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17959566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
17966823f3c5SBlaise Bourdin     }
17979566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
17981e50132fSMatthew G. Knepley #endif
17995f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
18005f34f2dcSJed Brown   } else if (iscgns) {
18015f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
18025f34f2dcSJed Brown #endif
18031baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1804cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
18059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1806cb3ba0daSMatthew G. Knepley   if (flg) {
1807cb3ba0daSMatthew G. Knepley     Vec ranks;
18089566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
18099566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
18109566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1811cb3ba0daSMatthew G. Knepley   }
1812002a2709SMatthew G. Knepley   /* Optionally view a label */
18139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1814002a2709SMatthew G. Knepley   if (flg) {
1815002a2709SMatthew G. Knepley     DMLabel label;
1816002a2709SMatthew G. Knepley     Vec     val;
1817002a2709SMatthew G. Knepley 
18189566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
181928b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
18209566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
18219566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
18229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1823002a2709SMatthew G. Knepley   }
18243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1825552f7358SJed Brown }
1826552f7358SJed Brown 
18277f96f51bSksagiyam /*@
1828a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
18297f96f51bSksagiyam 
183020f4b53cSBarry Smith   Collective
18317f96f51bSksagiyam 
18327f96f51bSksagiyam   Input Parameters:
1833a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
1834a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
18357f96f51bSksagiyam 
18367f96f51bSksagiyam   Level: advanced
18377f96f51bSksagiyam 
18381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
18397f96f51bSksagiyam @*/
1840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
1841d71ae5a4SJacob Faibussowitsch {
18427f96f51bSksagiyam   PetscBool ishdf5;
18437f96f51bSksagiyam 
18447f96f51bSksagiyam   PetscFunctionBegin;
18457f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18467f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
18497f96f51bSksagiyam   if (ishdf5) {
18507f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
18517f96f51bSksagiyam     PetscViewerFormat format;
18529566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18537f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18547f96f51bSksagiyam       IS globalPointNumbering;
18557f96f51bSksagiyam 
18569566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18579566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18589566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
185998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18607f96f51bSksagiyam #else
18617f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18627f96f51bSksagiyam #endif
18637f96f51bSksagiyam   }
18649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
18653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18667f96f51bSksagiyam }
18677f96f51bSksagiyam 
186877b8e257Sksagiyam /*@
1869a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
187077b8e257Sksagiyam 
187120f4b53cSBarry Smith   Collective
187277b8e257Sksagiyam 
187377b8e257Sksagiyam   Input Parameters:
1874a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
1875a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
187677b8e257Sksagiyam 
187777b8e257Sksagiyam   Level: advanced
187877b8e257Sksagiyam 
18791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
188077b8e257Sksagiyam @*/
1881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
1882d71ae5a4SJacob Faibussowitsch {
188377b8e257Sksagiyam   PetscBool ishdf5;
188477b8e257Sksagiyam 
188577b8e257Sksagiyam   PetscFunctionBegin;
188677b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
188777b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
189077b8e257Sksagiyam   if (ishdf5) {
189177b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
189277b8e257Sksagiyam     PetscViewerFormat format;
18939566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
189477b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18959566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
1896fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
189777b8e257Sksagiyam #else
189877b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
189977b8e257Sksagiyam #endif
190077b8e257Sksagiyam   }
19019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
19023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
190377b8e257Sksagiyam }
190477b8e257Sksagiyam 
1905bd6565f1Sksagiyam /*@
1906a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
1907bd6565f1Sksagiyam 
190820f4b53cSBarry Smith   Collective
1909bd6565f1Sksagiyam 
1910bd6565f1Sksagiyam   Input Parameters:
1911a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
1912a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
1913bd6565f1Sksagiyam 
1914bd6565f1Sksagiyam   Level: advanced
1915bd6565f1Sksagiyam 
19161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
1917bd6565f1Sksagiyam @*/
1918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1919d71ae5a4SJacob Faibussowitsch {
1920bd6565f1Sksagiyam   PetscBool ishdf5;
1921bd6565f1Sksagiyam 
1922bd6565f1Sksagiyam   PetscFunctionBegin;
1923bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1924bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
1927bd6565f1Sksagiyam   if (ishdf5) {
1928bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1929bd6565f1Sksagiyam     IS                globalPointNumbering;
1930bd6565f1Sksagiyam     PetscViewerFormat format;
1931bd6565f1Sksagiyam 
19329566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1933bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
19349566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
19359566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
19369566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
193798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1938bd6565f1Sksagiyam #else
1939bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1940bd6565f1Sksagiyam #endif
1941bd6565f1Sksagiyam   }
19429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
19433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1944bd6565f1Sksagiyam }
1945bd6565f1Sksagiyam 
1946021affd3Sksagiyam /*@
1947a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
1948021affd3Sksagiyam 
194920f4b53cSBarry Smith   Collective
1950021affd3Sksagiyam 
1951021affd3Sksagiyam   Input Parameters:
1952a1cb98faSBarry Smith + dm         - The `DM` that contains the topology on which the section to be saved is defined
1953a1cb98faSBarry Smith . viewer     - The `PetscViewer` for saving
1954a1cb98faSBarry Smith - sectiondm  - The `DM` that contains the section to be saved
1955021affd3Sksagiyam 
1956021affd3Sksagiyam   Level: advanced
1957021affd3Sksagiyam 
1958021affd3Sksagiyam   Notes:
1959a1cb98faSBarry 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.
1960021affd3Sksagiyam 
1961a1cb98faSBarry 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.
1962021affd3Sksagiyam 
19631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
1964021affd3Sksagiyam @*/
1965d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1966d71ae5a4SJacob Faibussowitsch {
1967021affd3Sksagiyam   PetscBool ishdf5;
1968021affd3Sksagiyam 
1969021affd3Sksagiyam   PetscFunctionBegin;
1970021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1971021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1972021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
1975021affd3Sksagiyam   if (ishdf5) {
1976021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19779566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1978021affd3Sksagiyam #else
1979021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1980021affd3Sksagiyam #endif
1981021affd3Sksagiyam   }
19829566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
19833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1984021affd3Sksagiyam }
1985021affd3Sksagiyam 
19863e97647fSksagiyam /*@
19873e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
19883e97647fSksagiyam 
198920f4b53cSBarry Smith   Collective
19903e97647fSksagiyam 
19913e97647fSksagiyam   Input Parameters:
1992a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
1993a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
1994a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
19953e97647fSksagiyam - vec       - The global vector to be saved
19963e97647fSksagiyam 
19973e97647fSksagiyam   Level: advanced
19983e97647fSksagiyam 
19993e97647fSksagiyam   Notes:
2000a1cb98faSBarry 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.
20013e97647fSksagiyam 
2002a1cb98faSBarry Smith   Typical calling sequence:
2003a1cb98faSBarry Smith .vb
2004a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2005a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2006a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2007a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2008a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2009a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2010a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2011a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2012a1cb98faSBarry Smith        PetscSectionSetUp(section);
2013a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2014a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2015a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2016a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2017a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2018a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2019a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2020a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2021a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2022a1cb98faSBarry Smith        DMDestroy(&dm);
2023a1cb98faSBarry Smith .ve
20243e97647fSksagiyam 
20251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20263e97647fSksagiyam @*/
2027d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2028d71ae5a4SJacob Faibussowitsch {
20293e97647fSksagiyam   PetscBool ishdf5;
20303e97647fSksagiyam 
20313e97647fSksagiyam   PetscFunctionBegin;
20323e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20333e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20343e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20353e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20363e97647fSksagiyam   /* Check consistency */
20373e97647fSksagiyam   {
20383e97647fSksagiyam     PetscSection section;
20393e97647fSksagiyam     PetscBool    includesConstraints;
20403e97647fSksagiyam     PetscInt     m, m1;
20413e97647fSksagiyam 
20429566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20439566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
20449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20459566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20469566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
204763a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
20483e97647fSksagiyam   }
20499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20509566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20513e97647fSksagiyam   if (ishdf5) {
20523e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20539566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20543e97647fSksagiyam #else
20553e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20563e97647fSksagiyam #endif
20573e97647fSksagiyam   }
20589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20603e97647fSksagiyam }
20613e97647fSksagiyam 
20623e97647fSksagiyam /*@
20633e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20643e97647fSksagiyam 
206520f4b53cSBarry Smith   Collective
20663e97647fSksagiyam 
20673e97647fSksagiyam   Input Parameters:
2068a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2069a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
207020f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm`
20713e97647fSksagiyam - vec       - The local vector to be saved
20723e97647fSksagiyam 
20733e97647fSksagiyam   Level: advanced
20743e97647fSksagiyam 
2075a1cb98faSBarry Smith   Note:
207620f4b53cSBarry 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.
20773e97647fSksagiyam 
2078a1cb98faSBarry Smith   Typical calling sequence:
2079a1cb98faSBarry Smith .vb
2080a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2081a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2082a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2083a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2084a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2085a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2086a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2087a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2088a1cb98faSBarry Smith        PetscSectionSetUp(section);
2089a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2090a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2091a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2092a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2093a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2094a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2095a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2096a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2097a1cb98faSBarry Smith        DMDestroy(&dm);
2098a1cb98faSBarry Smith .ve
20993e97647fSksagiyam 
21001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
21013e97647fSksagiyam @*/
2102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2103d71ae5a4SJacob Faibussowitsch {
21043e97647fSksagiyam   PetscBool ishdf5;
21053e97647fSksagiyam 
21063e97647fSksagiyam   PetscFunctionBegin;
21073e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21083e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21093e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21103e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
21113e97647fSksagiyam   /* Check consistency */
21123e97647fSksagiyam   {
21133e97647fSksagiyam     PetscSection section;
21143e97647fSksagiyam     PetscBool    includesConstraints;
21153e97647fSksagiyam     PetscInt     m, m1;
21163e97647fSksagiyam 
21179566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
21189566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
21199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
21209566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
21219566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
212263a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
21233e97647fSksagiyam   }
21249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
21263e97647fSksagiyam   if (ishdf5) {
21273e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
21289566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
21293e97647fSksagiyam #else
21303e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21313e97647fSksagiyam #endif
21323e97647fSksagiyam   }
21339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
21343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21353e97647fSksagiyam }
21363e97647fSksagiyam 
2137d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2138d71ae5a4SJacob Faibussowitsch {
2139d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
21402c40f234SMatthew G. Knepley 
21412c40f234SMatthew G. Knepley   PetscFunctionBegin;
21422c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21432c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2145d4f5a9a0SVaclav Hapla   if (ishdf5) {
21462c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
21479c48423bSVaclav Hapla     PetscViewerFormat format;
21489566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21499c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
21509566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2151509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21529566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
215398921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
21552c40f234SMatthew G. Knepley #else
21562c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2157552f7358SJed Brown #endif
215898921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2159552f7358SJed Brown }
2160552f7358SJed Brown 
2161ea8e1828Sksagiyam /*@
2162a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2163ea8e1828Sksagiyam 
216420f4b53cSBarry Smith   Collective
2165ea8e1828Sksagiyam 
2166ea8e1828Sksagiyam   Input Parameters:
2167a1cb98faSBarry Smith + dm                - The `DM` into which the topology is loaded
2168a1cb98faSBarry Smith - viewer            - The `PetscViewer` for the saved topology
2169ea8e1828Sksagiyam 
21702fe279fdSBarry Smith   Output Parameter:
217120f4b53cSBarry 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
2172dec9e869Sksagiyam 
2173ea8e1828Sksagiyam   Level: advanced
2174ea8e1828Sksagiyam 
21751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2176a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2177ea8e1828Sksagiyam @*/
2178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2179d71ae5a4SJacob Faibussowitsch {
2180ea8e1828Sksagiyam   PetscBool ishdf5;
2181ea8e1828Sksagiyam 
2182ea8e1828Sksagiyam   PetscFunctionBegin;
2183ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2184ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2185f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
21869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2188ea8e1828Sksagiyam   if (ishdf5) {
2189ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2190ea8e1828Sksagiyam     PetscViewerFormat format;
21919566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2192ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21939566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
219498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2195ea8e1828Sksagiyam #else
2196ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2197ea8e1828Sksagiyam #endif
2198ea8e1828Sksagiyam   }
21999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
22003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2201ea8e1828Sksagiyam }
2202ea8e1828Sksagiyam 
22033e701f1cSksagiyam /*@
2204a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
22053e701f1cSksagiyam 
220620f4b53cSBarry Smith   Collective
22073e701f1cSksagiyam 
22083e701f1cSksagiyam   Input Parameters:
2209a1cb98faSBarry Smith + dm     - The `DM` into which the coordinates are loaded
2210a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates
2211a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
22123e701f1cSksagiyam 
22133e701f1cSksagiyam   Level: advanced
22143e701f1cSksagiyam 
22151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2216a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
22173e701f1cSksagiyam @*/
2218d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2219d71ae5a4SJacob Faibussowitsch {
22203e701f1cSksagiyam   PetscBool ishdf5;
22213e701f1cSksagiyam 
22223e701f1cSksagiyam   PetscFunctionBegin;
22233e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22243e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2225c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
22283e701f1cSksagiyam   if (ishdf5) {
22293e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
22303e701f1cSksagiyam     PetscViewerFormat format;
22319566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
22323e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22339566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
223498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
22353e701f1cSksagiyam #else
22363e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22373e701f1cSksagiyam #endif
22383e701f1cSksagiyam   }
22399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
22403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22413e701f1cSksagiyam }
22423e701f1cSksagiyam 
2243b08ad5deSksagiyam /*@
2244a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2245b08ad5deSksagiyam 
224620f4b53cSBarry Smith   Collective
2247b08ad5deSksagiyam 
2248b08ad5deSksagiyam   Input Parameters:
2249a1cb98faSBarry Smith + dm     - The `DM` into which the labels are loaded
2250a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels
225120f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2252b08ad5deSksagiyam 
2253b08ad5deSksagiyam   Level: advanced
2254b08ad5deSksagiyam 
2255a1cb98faSBarry Smith   Note:
2256a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2257e6368b79SVaclav Hapla 
22581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2259a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2260b08ad5deSksagiyam @*/
2261d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2262d71ae5a4SJacob Faibussowitsch {
2263b08ad5deSksagiyam   PetscBool ishdf5;
2264b08ad5deSksagiyam 
2265b08ad5deSksagiyam   PetscFunctionBegin;
2266b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2267b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2268e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2271b08ad5deSksagiyam   if (ishdf5) {
2272b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2273b08ad5deSksagiyam     PetscViewerFormat format;
2274b08ad5deSksagiyam 
22759566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2276b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22779566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
227898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2279b08ad5deSksagiyam #else
2280b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2281b08ad5deSksagiyam #endif
2282b08ad5deSksagiyam   }
22839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
22843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2285b08ad5deSksagiyam }
2286b08ad5deSksagiyam 
2287f84dd6b4Sksagiyam /*@
2288a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2289f84dd6b4Sksagiyam 
229020f4b53cSBarry Smith   Collective
2291f84dd6b4Sksagiyam 
2292f84dd6b4Sksagiyam   Input Parameters:
2293a1cb98faSBarry Smith + dm          - The `DM` that represents the topology
2294a1cb98faSBarry Smith . viewer      - The `PetscViewer` that represents the on-disk section (sectionA)
2295a1cb98faSBarry Smith . sectiondm   - The `DM` into which the on-disk section (sectionA) is migrated
2296a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2297f84dd6b4Sksagiyam 
2298f84dd6b4Sksagiyam   Output Parameters
229920f4b53cSBarry 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)
230020f4b53cSBarry 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)
2301f84dd6b4Sksagiyam 
2302f84dd6b4Sksagiyam   Level: advanced
2303f84dd6b4Sksagiyam 
2304f84dd6b4Sksagiyam   Notes:
230520f4b53cSBarry 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.
2306f84dd6b4Sksagiyam 
230720f4b53cSBarry 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.
2308f84dd6b4Sksagiyam 
230920f4b53cSBarry 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.
2310f84dd6b4Sksagiyam 
2311f84dd6b4Sksagiyam   Example using 2 processes:
2312a1cb98faSBarry Smith .vb
2313a1cb98faSBarry Smith   NX (number of points on dm): 4
2314a1cb98faSBarry Smith   sectionA                   : the on-disk section
2315a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2316a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2317a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2318a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2319f84dd6b4Sksagiyam 
2320a1cb98faSBarry Smith                                      rank 0    rank 1
2321a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2322a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2323a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2324a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2325a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2326a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2327a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2328a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2329a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2330a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2331a1cb98faSBarry Smith .ve
2332a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2333a1cb98faSBarry Smith 
23341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2335f84dd6b4Sksagiyam @*/
2336d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2337d71ae5a4SJacob Faibussowitsch {
2338f84dd6b4Sksagiyam   PetscBool ishdf5;
2339f84dd6b4Sksagiyam 
2340f84dd6b4Sksagiyam   PetscFunctionBegin;
2341f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2342f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2343f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2344f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2345f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2346f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
23479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2349f84dd6b4Sksagiyam   if (ishdf5) {
2350f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
23519566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2352f84dd6b4Sksagiyam #else
2353f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2354f84dd6b4Sksagiyam #endif
2355f84dd6b4Sksagiyam   }
23569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
23573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2358f84dd6b4Sksagiyam }
2359f84dd6b4Sksagiyam 
23608be3dfe1Sksagiyam /*@
23618be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23628be3dfe1Sksagiyam 
236320f4b53cSBarry Smith   Collective
23648be3dfe1Sksagiyam 
23658be3dfe1Sksagiyam   Input Parameters:
2366a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2367a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2368a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
2369a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
23708be3dfe1Sksagiyam - vec       - The global vector to set values of
23718be3dfe1Sksagiyam 
23728be3dfe1Sksagiyam   Level: advanced
23738be3dfe1Sksagiyam 
23748be3dfe1Sksagiyam   Notes:
2375a1cb98faSBarry 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.
23768be3dfe1Sksagiyam 
2377a1cb98faSBarry Smith   Typical calling sequence:
2378a1cb98faSBarry Smith .vb
2379a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2380a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2381a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2382a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2383a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2384a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2385a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2386a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2387a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2388a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2389a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2390a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2391a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2392a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2393a1cb98faSBarry Smith        DMDestroy(&dm);
2394a1cb98faSBarry Smith .ve
23958be3dfe1Sksagiyam 
23961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2397a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
23988be3dfe1Sksagiyam @*/
2399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2400d71ae5a4SJacob Faibussowitsch {
24018be3dfe1Sksagiyam   PetscBool ishdf5;
24028be3dfe1Sksagiyam 
24038be3dfe1Sksagiyam   PetscFunctionBegin;
24048be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24058be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24068be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24078be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24088be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24098be3dfe1Sksagiyam   /* Check consistency */
24108be3dfe1Sksagiyam   {
24118be3dfe1Sksagiyam     PetscSection section;
24128be3dfe1Sksagiyam     PetscBool    includesConstraints;
24138be3dfe1Sksagiyam     PetscInt     m, m1;
24148be3dfe1Sksagiyam 
24159566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24169566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
24179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24189566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24199566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
242063a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
24218be3dfe1Sksagiyam   }
24229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
24248be3dfe1Sksagiyam   if (ishdf5) {
24258be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24269566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24278be3dfe1Sksagiyam #else
24288be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24298be3dfe1Sksagiyam #endif
24308be3dfe1Sksagiyam   }
24319566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
24323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24338be3dfe1Sksagiyam }
24348be3dfe1Sksagiyam 
24358be3dfe1Sksagiyam /*@
24368be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
24378be3dfe1Sksagiyam 
243820f4b53cSBarry Smith   Collective
24398be3dfe1Sksagiyam 
24408be3dfe1Sksagiyam   Input Parameters:
2441a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2442a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2443a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined
2444a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
24458be3dfe1Sksagiyam - vec       - The local vector to set values of
24468be3dfe1Sksagiyam 
24478be3dfe1Sksagiyam   Level: advanced
24488be3dfe1Sksagiyam 
24498be3dfe1Sksagiyam   Notes:
245020f4b53cSBarry 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.
24518be3dfe1Sksagiyam 
2452a1cb98faSBarry Smith   Typical calling sequence:
2453a1cb98faSBarry Smith .vb
2454a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2455a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2456a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2457a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2458a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2459a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2460a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2461a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2462a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2463a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2464a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2465a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2466a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2467a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2468a1cb98faSBarry Smith        DMDestroy(&dm);
2469a1cb98faSBarry Smith .ve
24708be3dfe1Sksagiyam 
24711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2472a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
24738be3dfe1Sksagiyam @*/
2474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2475d71ae5a4SJacob Faibussowitsch {
24768be3dfe1Sksagiyam   PetscBool ishdf5;
24778be3dfe1Sksagiyam 
24788be3dfe1Sksagiyam   PetscFunctionBegin;
24798be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24808be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24818be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24828be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24838be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24848be3dfe1Sksagiyam   /* Check consistency */
24858be3dfe1Sksagiyam   {
24868be3dfe1Sksagiyam     PetscSection section;
24878be3dfe1Sksagiyam     PetscBool    includesConstraints;
24888be3dfe1Sksagiyam     PetscInt     m, m1;
24898be3dfe1Sksagiyam 
24909566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24919566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
24929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24939566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24949566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
249563a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
24968be3dfe1Sksagiyam   }
24979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24989566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
24998be3dfe1Sksagiyam   if (ishdf5) {
25008be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
25019566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
25028be3dfe1Sksagiyam #else
25038be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
25048be3dfe1Sksagiyam #endif
25058be3dfe1Sksagiyam   }
25069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
25073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25088be3dfe1Sksagiyam }
25098be3dfe1Sksagiyam 
2510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2511d71ae5a4SJacob Faibussowitsch {
2512552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2513552f7358SJed Brown 
2514552f7358SJed Brown   PetscFunctionBegin;
25159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
25169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
25179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
25189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
25192e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
25202e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
25212e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
25222e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
25232e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
25246bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
25256bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2526c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2527c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
25285f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
25293ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
25309566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
25319566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
25329566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
25339566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
25349566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
25359566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
2536*21027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
25379f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
25389566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
25399566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
25409566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
25411d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
25429566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
25439566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
25449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
25459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
25469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
25474e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
25486725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
25496725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
25509566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
25519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
25529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
25539566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
25549566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
25559566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
25569566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
25579566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
25589566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
25599566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
25609566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2561552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
25629566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
25633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2564552f7358SJed Brown }
2565552f7358SJed Brown 
2566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2567d71ae5a4SJacob Faibussowitsch {
25688d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2569acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
25709fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2571837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2572b412c318SBarry Smith   MatType                mtype;
25731428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2574552f7358SJed Brown 
2575552f7358SJed Brown   PetscFunctionBegin;
25769566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2577b412c318SBarry Smith   mtype = dm->mattype;
25789566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25799566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25819fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
25829566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25839566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25849566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25859566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25869566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2587acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25889566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
25899566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25909566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25919566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25929566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25939566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25949566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25959566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2596552f7358SJed Brown   if (!isShell) {
2597837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
25989fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2599863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2600552f7358SJed Brown 
26019566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
26029fca9976SJed Brown 
26039fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
26049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2605863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2606e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2607863027abSJed Brown       switch (dm->blocking_type) {
26080e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
26099fca9976SJed Brown         PetscInt bdof, offset;
2610a9d99c84SMatthew G. Knepley 
26119566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
26129fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
26139566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
26149371c9d4SSatish Balay         for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof;
26151d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
26161d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
26171d17a0a3SMatthew G. Knepley         if (dof) {
26189371c9d4SSatish Balay           if (bs < 0) {
26199371c9d4SSatish Balay             bs = bdof;
26209371c9d4SSatish Balay           } else if (bs != bdof) {
26219371c9d4SSatish Balay             bs = 1;
26229371c9d4SSatish Balay           }
2623552f7358SJed Brown         }
2624863027abSJed Brown       } break;
2625863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2626863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2627863027abSJed Brown           PetscInt num_comp, bdof, offset;
2628863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2629863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2630863027abSJed Brown           if (dof < 0) continue;
2631863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2632863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2633863027abSJed 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);
2634863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2635863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2636863027abSJed Brown           // Handle possibly constant block size (unlikely)
2637863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2638863027abSJed Brown           if (dof) {
2639863027abSJed Brown             if (bs < 0) {
2640863027abSJed Brown               bs = bdof;
2641863027abSJed Brown             } else if (bs != bdof) {
2642863027abSJed Brown               bs = 1;
2643863027abSJed Brown             }
2644863027abSJed Brown           }
2645863027abSJed Brown         }
2646863027abSJed Brown       } break;
2647863027abSJed Brown       }
26482a28c762SMatthew G Knepley     }
26492a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2650e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2651e432b41dSStefano Zampini     bsLocal[1] = bs;
26529566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2653e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2654e432b41dSStefano Zampini     else bs = bsMinMax[0];
26556fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
26569566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
26570682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
26589566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
26599566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
26600682b8bbSJed Brown     } else {
26619566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
26629566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
26639566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2664552f7358SJed Brown     }
26659fca9976SJed Brown     { // Consolidate blocks
26669fca9976SJed Brown       PetscInt nblocks = 0;
26679fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
26689fca9976SJed Brown         if (pblocks[i] == 0) continue;
26699fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2670ad540459SPierre 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]);
26719fca9976SJed Brown       }
26729fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
26739fca9976SJed Brown     }
26749fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2675aa0f6e3cSJed Brown   }
26769566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
26773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2678552f7358SJed Brown }
2679552f7358SJed Brown 
26807cd05799SMatthew G. Knepley /*@
2681a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2682be36d101SStefano Zampini 
2683a1cb98faSBarry Smith   Not Collective
2684be36d101SStefano Zampini 
2685be36d101SStefano Zampini   Input Parameter:
2686a1cb98faSBarry Smith . mesh - The `DMPLEX`
2687be36d101SStefano Zampini 
26882fe279fdSBarry Smith   Output Parameter:
2689be36d101SStefano Zampini . subsection - The subdomain section
2690be36d101SStefano Zampini 
2691be36d101SStefano Zampini   Level: developer
2692be36d101SStefano Zampini 
26931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
26947cd05799SMatthew G. Knepley @*/
2695d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2696d71ae5a4SJacob Faibussowitsch {
2697be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2698be36d101SStefano Zampini 
2699be36d101SStefano Zampini   PetscFunctionBegin;
2700be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2701be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2702be36d101SStefano Zampini     PetscSection section;
2703be36d101SStefano Zampini     PetscSF      sf;
2704be36d101SStefano Zampini 
27059566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
27069566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27079566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
27089566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2709be36d101SStefano Zampini   }
2710be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
27113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2712be36d101SStefano Zampini }
2713be36d101SStefano Zampini 
2714552f7358SJed Brown /*@
271520f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2716552f7358SJed Brown 
2717a1cb98faSBarry Smith   Not Collective
2718552f7358SJed Brown 
2719552f7358SJed Brown   Input Parameter:
2720a1cb98faSBarry Smith . mesh - The `DMPLEX`
2721552f7358SJed Brown 
2722552f7358SJed Brown   Output Parameters:
2723552f7358SJed Brown + pStart - The first mesh point
2724552f7358SJed Brown - pEnd   - The upper bound for mesh points
2725552f7358SJed Brown 
2726552f7358SJed Brown   Level: beginner
2727552f7358SJed Brown 
27281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2729552f7358SJed Brown @*/
2730d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2731d71ae5a4SJacob Faibussowitsch {
2732552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2733552f7358SJed Brown 
2734552f7358SJed Brown   PetscFunctionBegin;
2735552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27369f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
27379f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
27383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2739552f7358SJed Brown }
2740552f7358SJed Brown 
2741552f7358SJed Brown /*@
274220f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2743552f7358SJed Brown 
2744a1cb98faSBarry Smith   Not Collective
2745552f7358SJed Brown 
2746552f7358SJed Brown   Input Parameters:
2747a1cb98faSBarry Smith + mesh - The `DMPLEX`
2748552f7358SJed Brown . pStart - The first mesh point
2749552f7358SJed Brown - pEnd   - The upper bound for mesh points
2750552f7358SJed Brown 
2751552f7358SJed Brown   Level: beginner
2752552f7358SJed Brown 
27531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2754552f7358SJed Brown @*/
2755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2756d71ae5a4SJacob Faibussowitsch {
2757552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2758*21027e53SStefano Zampini   PetscInt pStartO, pEndO;
2759552f7358SJed Brown 
2760552f7358SJed Brown   PetscFunctionBegin;
2761552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2762*21027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStartO, &pEndO));
27639566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
27649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2765*21027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
27663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2767552f7358SJed Brown }
2768552f7358SJed Brown 
2769552f7358SJed Brown /*@
2770eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2771552f7358SJed Brown 
2772a1cb98faSBarry Smith   Not Collective
2773552f7358SJed Brown 
2774552f7358SJed Brown   Input Parameters:
2775a1cb98faSBarry Smith + mesh - The `DMPLEX`
2776a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
2777552f7358SJed Brown 
2778552f7358SJed Brown   Output Parameter:
277920f4b53cSBarry Smith . size - The cone size for point `p`
2780552f7358SJed Brown 
2781552f7358SJed Brown   Level: beginner
2782552f7358SJed Brown 
27831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2784552f7358SJed Brown @*/
2785d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2786d71ae5a4SJacob Faibussowitsch {
2787552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2788552f7358SJed Brown 
2789552f7358SJed Brown   PetscFunctionBegin;
2790552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2791dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
27929f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
27939f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
27943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2795552f7358SJed Brown }
2796552f7358SJed Brown 
2797552f7358SJed Brown /*@
2798eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2799552f7358SJed Brown 
2800a1cb98faSBarry Smith   Not Collective
2801552f7358SJed Brown 
2802552f7358SJed Brown   Input Parameters:
2803a1cb98faSBarry Smith + mesh - The `DMPLEX`
2804a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
280520f4b53cSBarry Smith - size - The cone size for point `p`
2806552f7358SJed Brown 
2807552f7358SJed Brown   Level: beginner
2808552f7358SJed Brown 
2809a1cb98faSBarry Smith   Note:
2810a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
2811a1cb98faSBarry Smith 
28121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2813552f7358SJed Brown @*/
2814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2815d71ae5a4SJacob Faibussowitsch {
2816552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2817552f7358SJed Brown 
2818552f7358SJed Brown   PetscFunctionBegin;
2819552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28209f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
28219566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
28223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2823552f7358SJed Brown }
2824552f7358SJed Brown 
2825552f7358SJed Brown /*@C
2826eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2827552f7358SJed Brown 
2828a1cb98faSBarry Smith   Not Collective
2829552f7358SJed Brown 
2830552f7358SJed Brown   Input Parameters:
2831a1cb98faSBarry Smith + dm - The `DMPLEX`
2832a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
2833552f7358SJed Brown 
2834552f7358SJed Brown   Output Parameter:
283520f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
2836552f7358SJed Brown 
2837552f7358SJed Brown   Level: beginner
2838552f7358SJed Brown 
2839a1cb98faSBarry Smith   Fortran Note:
2840a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
2841a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
28423813dfbdSMatthew G Knepley 
28431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
2844552f7358SJed Brown @*/
2845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2846d71ae5a4SJacob Faibussowitsch {
2847552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2848552f7358SJed Brown   PetscInt off;
2849552f7358SJed Brown 
2850552f7358SJed Brown   PetscFunctionBegin;
2851552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2852552f7358SJed Brown   PetscValidPointer(cone, 3);
28539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2854552f7358SJed Brown   *cone = &mesh->cones[off];
28553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2856552f7358SJed Brown }
2857552f7358SJed Brown 
28580ce7577fSVaclav Hapla /*@C
28590ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
28600ce7577fSVaclav Hapla 
2861a1cb98faSBarry Smith   Not Collective
28620ce7577fSVaclav Hapla 
28630ce7577fSVaclav Hapla   Input Parameters:
2864a1cb98faSBarry Smith + dm - The `DMPLEX`
2865a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
28660ce7577fSVaclav Hapla 
2867d8d19677SJose E. Roman   Output Parameters:
286820f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
286920f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p`
28700ce7577fSVaclav Hapla 
28710ce7577fSVaclav Hapla   Level: intermediate
28720ce7577fSVaclav Hapla 
28731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
28740ce7577fSVaclav Hapla @*/
2875d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
2876d71ae5a4SJacob Faibussowitsch {
28770ce7577fSVaclav Hapla   PetscSection cs, newcs;
28780ce7577fSVaclav Hapla   PetscInt    *cones;
28790ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
28800ce7577fSVaclav Hapla   PetscInt     n;
28810ce7577fSVaclav Hapla 
28820ce7577fSVaclav Hapla   PetscFunctionBegin;
28839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28859566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
28860ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28870ce7577fSVaclav Hapla   if (pCones) {
28889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28899566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28900ce7577fSVaclav Hapla   }
28913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28920ce7577fSVaclav Hapla }
28930ce7577fSVaclav Hapla 
2894af9eab45SVaclav Hapla /*@
2895af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2896d4636a37SVaclav Hapla 
2897a1cb98faSBarry Smith   Not Collective
2898d4636a37SVaclav Hapla 
2899d4636a37SVaclav Hapla   Input Parameters:
2900a1cb98faSBarry Smith + dm - The `DMPLEX`
2901a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2902d4636a37SVaclav Hapla 
2903d4636a37SVaclav Hapla   Output Parameter:
2904af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2905d4636a37SVaclav Hapla 
2906d4636a37SVaclav Hapla   Level: advanced
2907d4636a37SVaclav Hapla 
2908af9eab45SVaclav Hapla   Notes:
290920f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
2910af9eab45SVaclav Hapla 
2911a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
2912a1cb98faSBarry Smith 
29131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
2914a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
2915d4636a37SVaclav Hapla @*/
2916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2917d71ae5a4SJacob Faibussowitsch {
2918af9eab45SVaclav Hapla   IS      *expandedPointsAll;
2919af9eab45SVaclav Hapla   PetscInt depth;
2920d4636a37SVaclav Hapla 
2921d4636a37SVaclav Hapla   PetscFunctionBegin;
2922af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2923af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2924af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
29259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2926af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
29279566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
29289566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
29293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2930af9eab45SVaclav Hapla }
2931af9eab45SVaclav Hapla 
2932af9eab45SVaclav Hapla /*@
2933af9eab45SVaclav 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).
2934af9eab45SVaclav Hapla 
2935a1cb98faSBarry Smith   Not Collective
2936af9eab45SVaclav Hapla 
2937af9eab45SVaclav Hapla   Input Parameters:
2938a1cb98faSBarry Smith + dm - The `DMPLEX`
2939a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2940af9eab45SVaclav Hapla 
2941d8d19677SJose E. Roman   Output Parameters:
2942a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
2943af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2944af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2945af9eab45SVaclav Hapla 
2946af9eab45SVaclav Hapla   Level: advanced
2947af9eab45SVaclav Hapla 
2948af9eab45SVaclav Hapla   Notes:
2949a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
2950af9eab45SVaclav Hapla 
295120f4b53cSBarry Smith   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.
2952af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2953af9eab45SVaclav Hapla 
295420f4b53cSBarry Smith   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:
295520f4b53cSBarry Smith   (1) DAG points in expandedPoints[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
295620f4b53cSBarry Smith   (2) DAG points in expandedPoints[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
2957af9eab45SVaclav Hapla 
29581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
2959a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
2960af9eab45SVaclav Hapla @*/
2961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2962d71ae5a4SJacob Faibussowitsch {
2963af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
2964af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
2965af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
2966af9eab45SVaclav Hapla   IS             *expandedPoints_;
2967af9eab45SVaclav Hapla   PetscSection   *sections_;
2968af9eab45SVaclav Hapla 
2969af9eab45SVaclav Hapla   PetscFunctionBegin;
2970af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2971af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2972af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2973af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2974af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
29759566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29769566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29789566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29799566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2980af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
2981af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
29829566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2984af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
2986af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29879566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29889566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2989af9eab45SVaclav Hapla       } else {
29909566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2991af9eab45SVaclav Hapla       }
2992af9eab45SVaclav Hapla     }
29939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2996af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2999af9eab45SVaclav Hapla       if (cn > 1) {
30009566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
30019566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3002af9eab45SVaclav Hapla       } else {
3003af9eab45SVaclav Hapla         newarr[co] = arr[i];
3004af9eab45SVaclav Hapla       }
3005af9eab45SVaclav Hapla     }
30069566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3007af9eab45SVaclav Hapla     arr = newarr;
3008af9eab45SVaclav Hapla     n   = newn;
3009af9eab45SVaclav Hapla   }
30109566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3011af9eab45SVaclav Hapla   *depth = depth_;
3012af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3013af9eab45SVaclav Hapla   else {
30149566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
30159566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3016af9eab45SVaclav Hapla   }
3017af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3018af9eab45SVaclav Hapla   else {
30199566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
30209566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3021af9eab45SVaclav Hapla   }
30223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3023af9eab45SVaclav Hapla }
3024af9eab45SVaclav Hapla 
3025af9eab45SVaclav Hapla /*@
3026a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3027af9eab45SVaclav Hapla 
3028a1cb98faSBarry Smith   Not Collective
3029af9eab45SVaclav Hapla 
3030af9eab45SVaclav Hapla   Input Parameters:
3031a1cb98faSBarry Smith + dm - The `DMPLEX`
3032a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3033af9eab45SVaclav Hapla 
3034d8d19677SJose E. Roman   Output Parameters:
3035a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3036af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3037af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
3038af9eab45SVaclav Hapla 
3039af9eab45SVaclav Hapla   Level: advanced
3040af9eab45SVaclav Hapla 
3041a1cb98faSBarry Smith   Note:
3042a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3043af9eab45SVaclav Hapla 
30441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3045a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3046af9eab45SVaclav Hapla @*/
3047d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3048d71ae5a4SJacob Faibussowitsch {
3049af9eab45SVaclav Hapla   PetscInt d, depth_;
3050af9eab45SVaclav Hapla 
3051af9eab45SVaclav Hapla   PetscFunctionBegin;
30529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
30531dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3054af9eab45SVaclav Hapla   if (depth) *depth = 0;
3055af9eab45SVaclav Hapla   if (expandedPoints) {
30569566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
30579566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3058af9eab45SVaclav Hapla   }
3059af9eab45SVaclav Hapla   if (sections) {
30609566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
30619566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3062af9eab45SVaclav Hapla   }
30633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3064d4636a37SVaclav Hapla }
3065d4636a37SVaclav Hapla 
3066552f7358SJed Brown /*@
306792371b87SBarry 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
3068552f7358SJed Brown 
3069a1cb98faSBarry Smith   Not Collective
3070552f7358SJed Brown 
3071552f7358SJed Brown   Input Parameters:
3072a1cb98faSBarry Smith + mesh - The `DMPLEX`
3073a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
307420f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3075552f7358SJed Brown 
3076552f7358SJed Brown   Level: beginner
3077552f7358SJed Brown 
3078a1cb98faSBarry Smith   Note:
3079a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3080a1cb98faSBarry Smith 
30811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3082552f7358SJed Brown @*/
3083d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3084d71ae5a4SJacob Faibussowitsch {
3085552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3086552f7358SJed Brown   PetscInt dof, off, c;
3087552f7358SJed Brown 
3088552f7358SJed Brown   PetscFunctionBegin;
3089552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3091dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3093db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3094db485b19SStefano Zampini     PetscInt pStart, pEnd;
3095db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
309663a3b9bcSJacob 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);
3097552f7358SJed Brown     for (c = 0; c < dof; ++c) {
309863a3b9bcSJacob 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);
3099552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3100552f7358SJed Brown     }
3101db485b19SStefano Zampini   } else {
3102db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3103db485b19SStefano Zampini   }
31043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3105552f7358SJed Brown }
3106552f7358SJed Brown 
3107552f7358SJed Brown /*@C
3108eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3109552f7358SJed Brown 
3110a1cb98faSBarry Smith   Not Collective
3111552f7358SJed Brown 
3112552f7358SJed Brown   Input Parameters:
3113a1cb98faSBarry Smith + mesh - The `DMPLEX`
3114a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3115552f7358SJed Brown 
3116552f7358SJed Brown   Output Parameter:
311720f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3118b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3119552f7358SJed Brown 
3120552f7358SJed Brown   Level: beginner
3121552f7358SJed Brown 
3122a1cb98faSBarry Smith   Note:
3123b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3124b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3125a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3126b5a892a1SMatthew G. Knepley   with the identity.
3127b5a892a1SMatthew G. Knepley 
3128a1cb98faSBarry Smith   Fortran Note:
3129a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3130a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
31313813dfbdSMatthew G Knepley 
31321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3133552f7358SJed Brown @*/
3134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3135d71ae5a4SJacob Faibussowitsch {
3136552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3137552f7358SJed Brown   PetscInt off;
3138552f7358SJed Brown 
3139552f7358SJed Brown   PetscFunctionBegin;
3140552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
314176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3142552f7358SJed Brown     PetscInt dof;
31439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3144552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3145552f7358SJed Brown   }
31469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
31470d644c17SKarl Rupp 
3148552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
31493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3150552f7358SJed Brown }
3151552f7358SJed Brown 
3152552f7358SJed Brown /*@
3153eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3154552f7358SJed Brown 
3155a1cb98faSBarry Smith   Not Collective
3156552f7358SJed Brown 
3157552f7358SJed Brown   Input Parameters:
3158a1cb98faSBarry Smith + mesh - The `DMPLEX`
3159a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
3160b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3161b5a892a1SMatthew G. Knepley 
3162552f7358SJed Brown   Level: beginner
3163552f7358SJed Brown 
3164a1cb98faSBarry Smith   Notes:
3165a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3166a1cb98faSBarry Smith 
3167a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3168a1cb98faSBarry Smith 
31691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3170552f7358SJed Brown @*/
3171d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3172d71ae5a4SJacob Faibussowitsch {
3173552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3174552f7358SJed Brown   PetscInt pStart, pEnd;
3175552f7358SJed Brown   PetscInt dof, off, c;
3176552f7358SJed Brown 
3177552f7358SJed Brown   PetscFunctionBegin;
3178552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3180dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
31819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3182db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3183db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
318463a3b9bcSJacob 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);
3185552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3186552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3187552f7358SJed Brown 
31889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
31891dca8a05SBarry 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);
3190552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3191552f7358SJed Brown     }
3192db485b19SStefano Zampini   } else {
3193db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3194db485b19SStefano Zampini   }
31953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3196552f7358SJed Brown }
3197552f7358SJed Brown 
31987cd05799SMatthew G. Knepley /*@
3199eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
32007cd05799SMatthew G. Knepley 
3201a1cb98faSBarry Smith   Not Collective
32027cd05799SMatthew G. Knepley 
32037cd05799SMatthew G. Knepley   Input Parameters:
3204a1cb98faSBarry Smith + mesh - The `DMPLEX`
3205a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
32067cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
32077cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
32087cd05799SMatthew G. Knepley 
32097cd05799SMatthew G. Knepley   Level: beginner
32107cd05799SMatthew G. Knepley 
32111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32127cd05799SMatthew G. Knepley @*/
3213d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3214d71ae5a4SJacob Faibussowitsch {
3215552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3216552f7358SJed Brown   PetscInt pStart, pEnd;
3217552f7358SJed Brown   PetscInt dof, off;
3218552f7358SJed Brown 
3219552f7358SJed Brown   PetscFunctionBegin;
3220552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3221a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
32229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
322363a3b9bcSJacob 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);
322463a3b9bcSJacob 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);
32259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
322663a3b9bcSJacob 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);
3227a03d55ffSStefano Zampini   }
3228a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3229552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
32303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3231552f7358SJed Brown }
3232552f7358SJed Brown 
32337cd05799SMatthew G. Knepley /*@
3234eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
32357cd05799SMatthew G. Knepley 
3236a1cb98faSBarry Smith   Not Collective
32377cd05799SMatthew G. Knepley 
32387cd05799SMatthew G. Knepley   Input Parameters:
3239a1cb98faSBarry Smith + mesh - The `DMPLEX`
3240a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
32417cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
32427cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
32437cd05799SMatthew G. Knepley 
32447cd05799SMatthew G. Knepley   Level: beginner
32457cd05799SMatthew G. Knepley 
3246a1cb98faSBarry Smith   Note:
3247a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3248b5a892a1SMatthew G. Knepley 
32491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32507cd05799SMatthew G. Knepley @*/
3251d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3252d71ae5a4SJacob Faibussowitsch {
325377c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
325477c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
325577c88f5bSMatthew G Knepley   PetscInt dof, off;
325677c88f5bSMatthew G Knepley 
325777c88f5bSMatthew G Knepley   PetscFunctionBegin;
325877c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3259a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
32609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
326163a3b9bcSJacob 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);
32629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
326363a3b9bcSJacob 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);
3264a03d55ffSStefano Zampini   }
3265a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
326677c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
32673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
326877c88f5bSMatthew G Knepley }
326977c88f5bSMatthew G Knepley 
32709f4ada15SMatthew G. Knepley /*@C
32719f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
32729f4ada15SMatthew G. Knepley 
32739f4ada15SMatthew G. Knepley   Not collective
32749f4ada15SMatthew G. Knepley 
32759f4ada15SMatthew G. Knepley   Input Parameters:
32769f4ada15SMatthew G. Knepley + dm - The DMPlex
32779f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
32789f4ada15SMatthew G. Knepley 
32799f4ada15SMatthew G. Knepley   Output Parameters:
328020f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
328120f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
32829f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
32839f4ada15SMatthew G. Knepley 
32849f4ada15SMatthew G. Knepley   Level: beginner
32859f4ada15SMatthew G. Knepley 
32869f4ada15SMatthew G. Knepley   Notes:
32879f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
32889f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
328920f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
32909f4ada15SMatthew G. Knepley   with the identity.
32919f4ada15SMatthew G. Knepley 
32929f4ada15SMatthew G. Knepley   Fortran Notes:
329320f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
329420f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
32959f4ada15SMatthew G. Knepley 
32961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
32979f4ada15SMatthew G. Knepley @*/
32989f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
32999f4ada15SMatthew G. Knepley {
33009f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
33019f4ada15SMatthew G. Knepley 
33029f4ada15SMatthew G. Knepley   PetscFunctionBegin;
33039f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33049f4ada15SMatthew G. Knepley   if (mesh->tr) {
33059f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
33069f4ada15SMatthew G. Knepley   } else {
33079f4ada15SMatthew G. Knepley     PetscInt off;
33089f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
33099f4ada15SMatthew G. Knepley       PetscInt dof;
33109f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33119f4ada15SMatthew G. Knepley       if (dof) {
33129f4ada15SMatthew G. Knepley         if (cone) PetscValidPointer(cone, 3);
33139f4ada15SMatthew G. Knepley         if (ornt) PetscValidPointer(ornt, 4);
33149f4ada15SMatthew G. Knepley       }
33159f4ada15SMatthew G. Knepley     }
33169f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33179f4ada15SMatthew G. Knepley     if (cone) *cone = &mesh->cones[off];
33189f4ada15SMatthew G. Knepley     if (ornt) *ornt = &mesh->coneOrientations[off];
33199f4ada15SMatthew G. Knepley   }
33203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33219f4ada15SMatthew G. Knepley }
33229f4ada15SMatthew G. Knepley 
33239f4ada15SMatthew G. Knepley /*@C
33249f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
33259f4ada15SMatthew G. Knepley 
332620f4b53cSBarry Smith   Not Collective
33279f4ada15SMatthew G. Knepley 
33289f4ada15SMatthew G. Knepley   Input Parameters:
33299f4ada15SMatthew G. Knepley + dm - The DMPlex
333020f4b53cSBarry Smith . p  - The point, which must lie in the chart set with `DMPlexSetChart()`
33319f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
333220f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
33339f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
33349f4ada15SMatthew G. Knepley 
33359f4ada15SMatthew G. Knepley   Level: beginner
33369f4ada15SMatthew G. Knepley 
33379f4ada15SMatthew G. Knepley   Notes:
33389f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
33399f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
334020f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
33419f4ada15SMatthew G. Knepley   with the identity.
33429f4ada15SMatthew G. Knepley 
334320f4b53cSBarry Smith   Fortran Note:
334420f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
334520f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
33469f4ada15SMatthew G. Knepley 
33471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
33489f4ada15SMatthew G. Knepley @*/
33499f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
33509f4ada15SMatthew G. Knepley {
33519f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
33529f4ada15SMatthew G. Knepley 
33539f4ada15SMatthew G. Knepley   PetscFunctionBegin;
33549f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33559f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
33563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33579f4ada15SMatthew G. Knepley }
33589f4ada15SMatthew G. Knepley 
3359552f7358SJed Brown /*@
3360eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3361552f7358SJed Brown 
3362a1cb98faSBarry Smith   Not Collective
3363552f7358SJed Brown 
3364552f7358SJed Brown   Input Parameters:
3365a1cb98faSBarry Smith + mesh - The `DMPLEX`
3366a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3367552f7358SJed Brown 
3368552f7358SJed Brown   Output Parameter:
336920f4b53cSBarry Smith . size - The support size for point `p`
3370552f7358SJed Brown 
3371552f7358SJed Brown   Level: beginner
3372552f7358SJed Brown 
33731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3374552f7358SJed Brown @*/
3375d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3376d71ae5a4SJacob Faibussowitsch {
3377552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3378552f7358SJed Brown 
3379552f7358SJed Brown   PetscFunctionBegin;
3380552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3381dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
33829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
33833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3384552f7358SJed Brown }
3385552f7358SJed Brown 
3386552f7358SJed Brown /*@
3387eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3388552f7358SJed Brown 
3389a1cb98faSBarry Smith   Not Collective
3390552f7358SJed Brown 
3391552f7358SJed Brown   Input Parameters:
3392a1cb98faSBarry Smith + mesh - The `DMPLEX`
3393a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
339420f4b53cSBarry Smith - size - The support size for point `p`
3395552f7358SJed Brown 
3396a1cb98faSBarry Smith   Level: beginner
3397552f7358SJed Brown 
3398552f7358SJed Brown   Note:
339920f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3400552f7358SJed Brown 
34011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3402552f7358SJed Brown @*/
3403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3404d71ae5a4SJacob Faibussowitsch {
3405552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3406552f7358SJed Brown 
3407552f7358SJed Brown   PetscFunctionBegin;
3408552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34099566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
34103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3411552f7358SJed Brown }
3412552f7358SJed Brown 
3413552f7358SJed Brown /*@C
3414eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3415552f7358SJed Brown 
3416a1cb98faSBarry Smith   Not Collective
3417552f7358SJed Brown 
3418552f7358SJed Brown   Input Parameters:
3419a1cb98faSBarry Smith + mesh - The `DMPLEX`
3420a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3421552f7358SJed Brown 
3422552f7358SJed Brown   Output Parameter:
342320f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3424552f7358SJed Brown 
3425552f7358SJed Brown   Level: beginner
3426552f7358SJed Brown 
3427a1cb98faSBarry Smith   Fortran Note:
3428a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3429a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
34303813dfbdSMatthew G Knepley 
34311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3432552f7358SJed Brown @*/
3433d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3434d71ae5a4SJacob Faibussowitsch {
3435552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3436552f7358SJed Brown   PetscInt off;
3437552f7358SJed Brown 
3438552f7358SJed Brown   PetscFunctionBegin;
3439552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3440552f7358SJed Brown   PetscValidPointer(support, 3);
34419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3442552f7358SJed Brown   *support = &mesh->supports[off];
34433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3444552f7358SJed Brown }
3445552f7358SJed Brown 
3446552f7358SJed Brown /*@
344792371b87SBarry 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
3448552f7358SJed Brown 
3449a1cb98faSBarry Smith   Not Collective
3450552f7358SJed Brown 
3451552f7358SJed Brown   Input Parameters:
3452a1cb98faSBarry Smith + mesh - The `DMPLEX`
3453a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
345420f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3455552f7358SJed Brown 
3456552f7358SJed Brown   Level: beginner
3457552f7358SJed Brown 
3458a1cb98faSBarry Smith   Note:
3459a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3460a1cb98faSBarry Smith 
34611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3462552f7358SJed Brown @*/
3463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3464d71ae5a4SJacob Faibussowitsch {
3465552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3466552f7358SJed Brown   PetscInt pStart, pEnd;
3467552f7358SJed Brown   PetscInt dof, off, c;
3468552f7358SJed Brown 
3469552f7358SJed Brown   PetscFunctionBegin;
3470552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
34729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3473dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
34749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
347563a3b9bcSJacob 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);
3476552f7358SJed Brown   for (c = 0; c < dof; ++c) {
347763a3b9bcSJacob 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);
3478552f7358SJed Brown     mesh->supports[off + c] = support[c];
3479552f7358SJed Brown   }
34803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3481552f7358SJed Brown }
3482552f7358SJed Brown 
34837cd05799SMatthew G. Knepley /*@
3484eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
34857cd05799SMatthew G. Knepley 
3486a1cb98faSBarry Smith   Not Collective
34877cd05799SMatthew G. Knepley 
34887cd05799SMatthew G. Knepley   Input Parameters:
3489a1cb98faSBarry Smith + mesh - The `DMPLEX`
3490a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
34917cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
34927cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
34937cd05799SMatthew G. Knepley 
34947cd05799SMatthew G. Knepley   Level: beginner
34957cd05799SMatthew G. Knepley 
34961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34977cd05799SMatthew G. Knepley @*/
3498d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3499d71ae5a4SJacob Faibussowitsch {
3500552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3501552f7358SJed Brown   PetscInt pStart, pEnd;
3502552f7358SJed Brown   PetscInt dof, off;
3503552f7358SJed Brown 
3504552f7358SJed Brown   PetscFunctionBegin;
3505552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
35079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
35089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
350963a3b9bcSJacob 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);
351063a3b9bcSJacob 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);
351163a3b9bcSJacob 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);
3512552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
35133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3514552f7358SJed Brown }
3515552f7358SJed Brown 
3516b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3517d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3518d71ae5a4SJacob Faibussowitsch {
3519b5a892a1SMatthew G. Knepley   switch (ct) {
3520b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3521b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3522b5a892a1SMatthew G. Knepley     break;
3523b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3524b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3525b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3526b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3527b5a892a1SMatthew G. Knepley     break;
3528b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3529b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3530b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3531b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3532b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3533b5a892a1SMatthew G. Knepley     break;
3534d71ae5a4SJacob Faibussowitsch   default:
3535d71ae5a4SJacob Faibussowitsch     return o;
3536b5a892a1SMatthew G. Knepley   }
3537b5a892a1SMatthew G. Knepley   return o;
3538b5a892a1SMatthew G. Knepley }
3539b5a892a1SMatthew G. Knepley 
3540b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3541d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3542d71ae5a4SJacob Faibussowitsch {
3543b5a892a1SMatthew G. Knepley   switch (ct) {
3544b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3545b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3546b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3547b5a892a1SMatthew G. Knepley     break;
3548b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3549b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3550b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3551b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3552b5a892a1SMatthew G. Knepley     break;
3553b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3554b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3555b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3556b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3557b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3558b5a892a1SMatthew G. Knepley     break;
3559d71ae5a4SJacob Faibussowitsch   default:
3560d71ae5a4SJacob Faibussowitsch     return o;
3561b5a892a1SMatthew G. Knepley   }
3562b5a892a1SMatthew G. Knepley   return o;
3563b5a892a1SMatthew G. Knepley }
3564b5a892a1SMatthew G. Knepley 
3565b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3567d71ae5a4SJacob Faibussowitsch {
3568b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3569b5a892a1SMatthew G. Knepley 
3570b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
35719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3572b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3573b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3574b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3575b5a892a1SMatthew G. Knepley 
35769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
35779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
35789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3579b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3580b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3581b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3582b5a892a1SMatthew G. Knepley 
35839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3584b5a892a1SMatthew G. Knepley       switch (ct) {
3585b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
35869566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35879566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3588b5a892a1SMatthew G. Knepley         break;
3589b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
35909566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
35919566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35929566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3593b5a892a1SMatthew G. Knepley         break;
3594b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
35959566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
35969566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35979566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
35989566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3599b5a892a1SMatthew G. Knepley         break;
3600d71ae5a4SJacob Faibussowitsch       default:
3601d71ae5a4SJacob Faibussowitsch         break;
3602b5a892a1SMatthew G. Knepley       }
3603b5a892a1SMatthew G. Knepley     }
3604b5a892a1SMatthew G. Knepley   }
36053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3606b5a892a1SMatthew G. Knepley }
3607b5a892a1SMatthew G. Knepley 
3608d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3609d71ae5a4SJacob Faibussowitsch {
3610b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3611b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3612b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3613b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3614b5a892a1SMatthew G. Knepley 
3615b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3616b5a892a1SMatthew G. Knepley   if (ornt) {
36179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3618b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3619b5a892a1SMatthew G. Knepley   }
3620b5a892a1SMatthew G. Knepley   if (*points) {
3621b5a892a1SMatthew G. Knepley     closure = *points;
3622b5a892a1SMatthew G. Knepley   } else {
3623b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
36249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
36259566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3626b5a892a1SMatthew G. Knepley   }
3627b5a892a1SMatthew G. Knepley   if (useCone) {
36289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
36299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
36309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3631b5a892a1SMatthew G. Knepley   } else {
36329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
36339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3634b5a892a1SMatthew G. Knepley   }
3635b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3636b5a892a1SMatthew G. Knepley     closure[off++] = p;
3637b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3638b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3639b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3640b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3641b5a892a1SMatthew G. Knepley     }
3642b5a892a1SMatthew G. Knepley   } else {
36435f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3644b5a892a1SMatthew G. Knepley 
3645b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3646b5a892a1SMatthew G. Knepley     closure[off++] = p;
3647b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3648b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3649b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3650b5a892a1SMatthew G. Knepley 
36519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3652b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3653b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3654b5a892a1SMatthew G. Knepley     }
3655b5a892a1SMatthew G. Knepley   }
3656b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3657b5a892a1SMatthew G. Knepley   if (points) *points = closure;
36583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3659b5a892a1SMatthew G. Knepley }
3660b5a892a1SMatthew G. Knepley 
3661d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3662d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3663d71ae5a4SJacob Faibussowitsch {
3664b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3665b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3666b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3667b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3668b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3669b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3670b5a892a1SMatthew G. Knepley 
3671b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
36729566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
36739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
36749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
36759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
36769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3677b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3678b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3679b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
36809371c9d4SSatish Balay   if (*points) {
36819371c9d4SSatish Balay     pts = *points;
36829371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3683b5a892a1SMatthew G. Knepley   c        = 0;
3684b5a892a1SMatthew G. Knepley   pts[c++] = point;
3685b5a892a1SMatthew G. Knepley   pts[c++] = o;
36869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
36879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
36889371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
36899371c9d4SSatish Balay     pts[c++] = closure[cl];
36909371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
36919371c9d4SSatish Balay   }
36929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
36939371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
36949371c9d4SSatish Balay     pts[c++] = closure[cl];
36959371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
36969371c9d4SSatish Balay   }
36979566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3698b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
36999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3700b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3701b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3702b5a892a1SMatthew G. Knepley   }
3703b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3704b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3705b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3706b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3707b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3708b5a892a1SMatthew G. Knepley 
37099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3710b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
37119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
37129566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
37139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3714b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3715b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3716b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3717b5a892a1SMatthew G. Knepley 
37189371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
37199371c9d4SSatish Balay           if (pts[i] == cp) break;
3720b5a892a1SMatthew G. Knepley         if (i == c) {
37219566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3722b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3723b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3724b5a892a1SMatthew G. Knepley         }
3725b5a892a1SMatthew G. Knepley       }
3726b5a892a1SMatthew G. Knepley     }
3727b5a892a1SMatthew G. Knepley   }
3728b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3729b5a892a1SMatthew G. Knepley   *points    = pts;
37303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3731b5a892a1SMatthew G. Knepley }
3732b5a892a1SMatthew G. Knepley 
3733d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3734d71ae5a4SJacob Faibussowitsch {
3735b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3736b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3737b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3738b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3739b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3740b5a892a1SMatthew G. Knepley 
3741b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
37429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3743b5a892a1SMatthew G. Knepley   if (depth == 1) {
37449566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
37453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3746b5a892a1SMatthew G. Knepley   }
37479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3748b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3749b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
37509566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
37513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3752b5a892a1SMatthew G. Knepley   }
37539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3754b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3755b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3756b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
37579566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
37589371c9d4SSatish Balay   if (*points) {
37599371c9d4SSatish Balay     closure = *points;
37609371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3761b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3762b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3763b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3764b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3765b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3766b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3767b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3768b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3769b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3770b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
3771b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3772b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3773b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3774b5a892a1SMatthew G. Knepley 
3775b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3776b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2;
377763a3b9bcSJacob 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);
3778b5a892a1SMatthew G. Knepley     }
3779b5a892a1SMatthew G. Knepley     if (useCone) {
37809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
37819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
37829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3783b5a892a1SMatthew G. Knepley     } else {
37849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
37859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3786b5a892a1SMatthew G. Knepley       tmpO = NULL;
3787b5a892a1SMatthew G. Knepley     }
3788b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3789b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
3790b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
3791b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
37929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3793b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3794b5a892a1SMatthew G. Knepley       PetscInt       c;
3795b5a892a1SMatthew G. Knepley 
3796b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3797b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3798b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3799b5a892a1SMatthew G. Knepley       }
3800b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3801b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3802b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3803b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3804b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3805b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3806b5a892a1SMatthew G. Knepley       }
3807b5a892a1SMatthew G. Knepley     }
3808b5a892a1SMatthew G. Knepley   }
38099566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
3810b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
3811b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3813b5a892a1SMatthew G. Knepley }
3814b5a892a1SMatthew G. Knepley 
3815552f7358SJed Brown /*@C
3816eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3817552f7358SJed Brown 
3818a1cb98faSBarry Smith   Not Collective
3819552f7358SJed Brown 
3820552f7358SJed Brown   Input Parameters:
3821a1cb98faSBarry Smith + dm      - The `DMPLEX`
3822b5a892a1SMatthew G. Knepley . p       - The mesh point
3823a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
3824552f7358SJed Brown 
38256b867d5aSJose E. Roman   Input/Output Parameter:
38266b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
382720f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
38286b867d5aSJose E. Roman 
38296b867d5aSJose E. Roman   Output Parameter:
383020f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
3831552f7358SJed Brown 
3832a1cb98faSBarry Smith   Level: beginner
3833a1cb98faSBarry Smith 
3834552f7358SJed Brown   Note:
383520f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
3836552f7358SJed Brown 
38379f22da38SBarry Smith   Fortran Note:
383820f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
38393813dfbdSMatthew G Knepley 
38401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3841552f7358SJed Brown @*/
3842d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3843d71ae5a4SJacob Faibussowitsch {
3844b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3845552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3846b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3847b5a892a1SMatthew G. Knepley   if (points) PetscValidPointer(points, 5);
38489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
38493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38509bf0dad6SMatthew G. Knepley }
38519bf0dad6SMatthew G. Knepley 
3852552f7358SJed Brown /*@C
3853eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3854552f7358SJed Brown 
3855a1cb98faSBarry Smith   Not Collective
3856552f7358SJed Brown 
3857552f7358SJed Brown   Input Parameters:
3858a1cb98faSBarry Smith + dm        - The `DMPLEX`
3859b5a892a1SMatthew G. Knepley . p         - The mesh point
3860a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
386120f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
3862b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3863552f7358SJed Brown 
3864a1cb98faSBarry Smith   Level: beginner
3865a1cb98faSBarry Smith 
3866552f7358SJed Brown   Note:
386720f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
3868552f7358SJed Brown 
38691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3870552f7358SJed Brown @*/
3871d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3872d71ae5a4SJacob Faibussowitsch {
3873b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3874552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38754ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
38769566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
38773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3878552f7358SJed Brown }
3879552f7358SJed Brown 
3880552f7358SJed Brown /*@
3881eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3882552f7358SJed Brown 
3883a1cb98faSBarry Smith   Not Collective
3884552f7358SJed Brown 
3885552f7358SJed Brown   Input Parameter:
3886a1cb98faSBarry Smith . mesh - The `DMPLEX`
3887552f7358SJed Brown 
3888552f7358SJed Brown   Output Parameters:
3889552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3890552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3891552f7358SJed Brown 
3892552f7358SJed Brown   Level: beginner
3893552f7358SJed Brown 
38941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3895552f7358SJed Brown @*/
3896d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3897d71ae5a4SJacob Faibussowitsch {
3898552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3899552f7358SJed Brown 
3900552f7358SJed Brown   PetscFunctionBegin;
3901552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39021baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
39031baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
39043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3905552f7358SJed Brown }
3906552f7358SJed Brown 
3907d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
3908d71ae5a4SJacob Faibussowitsch {
3909552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
39106302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
3911552f7358SJed Brown 
3912552f7358SJed Brown   PetscFunctionBegin;
3913552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
39159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
39169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
39179566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
39186302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
39196302a7fbSVaclav Hapla   if (maxSupportSize) {
39209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
39219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
39229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
3923552f7358SJed Brown   }
39243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3925552f7358SJed Brown }
3926552f7358SJed Brown 
3927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3928d71ae5a4SJacob Faibussowitsch {
3929552f7358SJed Brown   PetscFunctionBegin;
39309566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
39319566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3932ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
3933736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
393495602cf2SAlexis Marboeuf     PetscSF sfNatural;
3935f94b4a02SBlaise Bourdin 
39363dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
39379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
393895602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
3939c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3940f94b4a02SBlaise Bourdin   }
39413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3942552f7358SJed Brown }
3943552f7358SJed Brown 
3944d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
3945d71ae5a4SJacob Faibussowitsch {
39463dcd263cSBlaise Bourdin   PetscInt i = 0;
39472adcc780SMatthew G. Knepley 
39482adcc780SMatthew G. Knepley   PetscFunctionBegin;
39499566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
39509566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3951c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
39523dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
39533dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
395495602cf2SAlexis Marboeuf       PetscSF sfNatural;
39553dcd263cSBlaise Bourdin 
39563dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
39579566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
3958c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
395995602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
3960c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
39613dcd263cSBlaise Bourdin       break;
39623dcd263cSBlaise Bourdin     }
39633dcd263cSBlaise Bourdin   }
39643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39652adcc780SMatthew G. Knepley }
39662adcc780SMatthew G. Knepley 
3967552f7358SJed Brown /*@
3968eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3969552f7358SJed Brown 
3970a1cb98faSBarry Smith   Not Collective
3971552f7358SJed Brown 
3972552f7358SJed Brown   Input Parameter:
3973a1cb98faSBarry Smith . mesh - The `DMPLEX`
3974552f7358SJed Brown 
3975552f7358SJed Brown   Level: beginner
3976552f7358SJed Brown 
3977a1cb98faSBarry Smith   Note:
3978a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
3979a1cb98faSBarry Smith 
39801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3981552f7358SJed Brown @*/
3982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
3983d71ae5a4SJacob Faibussowitsch {
3984552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
3985552f7358SJed Brown   PetscInt *offsets;
3986552f7358SJed Brown   PetscInt  supportSize;
3987552f7358SJed Brown   PetscInt  pStart, pEnd, p;
3988552f7358SJed Brown 
3989552f7358SJed Brown   PetscFunctionBegin;
3990552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
399128b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
39929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
3993552f7358SJed Brown   /* Calculate support sizes */
39949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3995552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3996552f7358SJed Brown     PetscInt dof, off, c;
3997552f7358SJed Brown 
39989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
39999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
400048a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4001552f7358SJed Brown   }
40029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4003552f7358SJed Brown   /* Calculate supports */
40049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
40059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
40069566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4007552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4008552f7358SJed Brown     PetscInt dof, off, c;
4009552f7358SJed Brown 
40109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
40119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4012552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4013552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4014552f7358SJed Brown       PetscInt       offS;
4015552f7358SJed Brown 
40169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
40170d644c17SKarl Rupp 
4018552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4019552f7358SJed Brown       ++offsets[q];
4020552f7358SJed Brown     }
4021552f7358SJed Brown   }
40229566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
40239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
40243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4025552f7358SJed Brown }
4026552f7358SJed Brown 
4027d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4028d71ae5a4SJacob Faibussowitsch {
4029277ea44aSLisandro Dalcin   IS stratumIS;
4030277ea44aSLisandro Dalcin 
4031277ea44aSLisandro Dalcin   PetscFunctionBegin;
40323ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
403376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4034277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4035277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
40369566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4037277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
40389566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
40399371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
40409371c9d4SSatish Balay         overlap = PETSC_TRUE;
40419371c9d4SSatish Balay         break;
40429371c9d4SSatish Balay       }
4043277ea44aSLisandro Dalcin     }
404463a3b9bcSJacob 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);
4045277ea44aSLisandro Dalcin   }
40469566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
40479566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
40489566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
40493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4050277ea44aSLisandro Dalcin }
4051277ea44aSLisandro Dalcin 
4052552f7358SJed Brown /*@
4053a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
40546dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
4055552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
4056552f7358SJed Brown   the DAG.
4057552f7358SJed Brown 
405820f4b53cSBarry Smith   Collective
4059552f7358SJed Brown 
4060552f7358SJed Brown   Input Parameter:
4061a1cb98faSBarry Smith . mesh - The `DMPLEX`
4062552f7358SJed Brown 
4063a1cb98faSBarry Smith   Level: beginner
4064552f7358SJed Brown 
4065552f7358SJed Brown   Notes:
4066a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4067b1bb481bSMatthew 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
4068a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4069a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4070a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4071552f7358SJed Brown 
4072b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4073b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4074b1bb481bSMatthew 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
4075b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4076a1cb98faSBarry Smith .vb
4077a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4078a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4079a1cb98faSBarry Smith .ve
4080a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4081a1cb98faSBarry Smith .vb
4082a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4083a1cb98faSBarry Smith    depth 1 = {e0, c0}
4084a1cb98faSBarry Smith .ve
4085b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4086b1bb481bSMatthew Knepley 
4087a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4088552f7358SJed Brown 
40891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4090552f7358SJed Brown @*/
4091d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4092d71ae5a4SJacob Faibussowitsch {
4093df0420ecSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4094aa50250dSMatthew G. Knepley   DMLabel  label;
4095552f7358SJed Brown   PetscInt pStart, pEnd, p;
4096552f7358SJed Brown   PetscInt numRoots = 0, numLeaves = 0;
4097552f7358SJed Brown 
4098552f7358SJed Brown   PetscFunctionBegin;
4099552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4101277ea44aSLisandro Dalcin 
4102277ea44aSLisandro Dalcin   /* Create depth label */
41039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
41049566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
41059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4106277ea44aSLisandro Dalcin 
4107277ea44aSLisandro Dalcin   {
4108552f7358SJed Brown     /* Initialize roots and count leaves */
4109277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4110277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4111552f7358SJed Brown     PetscInt coneSize, supportSize;
4112552f7358SJed Brown 
4113277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
41149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4116552f7358SJed Brown       if (!coneSize && supportSize) {
4117277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4118277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4119552f7358SJed Brown         ++numRoots;
4120552f7358SJed Brown       } else if (!supportSize && coneSize) {
4121552f7358SJed Brown         ++numLeaves;
4122552f7358SJed Brown       } else if (!supportSize && !coneSize) {
4123552f7358SJed Brown         /* Isolated points */
4124277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4125277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4126552f7358SJed Brown       }
4127552f7358SJed Brown     }
41289566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4129277ea44aSLisandro Dalcin   }
4130277ea44aSLisandro Dalcin 
4131552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
4132277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4133277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4134552f7358SJed Brown     PetscInt coneSize, supportSize;
4135552f7358SJed Brown 
4136277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
41379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41389566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4139552f7358SJed Brown       if (!supportSize && coneSize) {
4140277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4141277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4142552f7358SJed Brown       }
4143552f7358SJed Brown     }
41449566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4145552f7358SJed Brown   } else {
4146277ea44aSLisandro Dalcin     PetscInt level = 0;
4147277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
4148552f7358SJed Brown 
41499566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4150277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4151277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4152277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
415374ef644bSMatthew G. Knepley 
4154277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
415574ef644bSMatthew G. Knepley         const PetscInt *support;
415674ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
415774ef644bSMatthew G. Knepley 
41589566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
41599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
416074ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4161277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4162277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4163552f7358SJed Brown         }
4164552f7358SJed Brown       }
41659566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
41669566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
41679566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
416874ef644bSMatthew G. Knepley     }
416974ef644bSMatthew G. Knepley   }
4170bf4602e4SToby Isaac   { /* just in case there is an empty process */
4171bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4172bf4602e4SToby Isaac 
41739566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4174712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
417548a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4176bf4602e4SToby Isaac   }
41779566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
41789566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
41793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4180552f7358SJed Brown }
4181552f7358SJed Brown 
4182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4183d71ae5a4SJacob Faibussowitsch {
4184412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4185412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4186ba2698f1SMatthew G. Knepley 
4187412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
41889566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
41899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
41909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4191ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4192ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4193ba2698f1SMatthew G. Knepley     switch (pdepth) {
4194d71ae5a4SJacob Faibussowitsch     case 0:
4195d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4196d71ae5a4SJacob Faibussowitsch       break;
4197ba2698f1SMatthew G. Knepley     case 1:
4198ba2698f1SMatthew G. Knepley       switch (coneSize) {
4199d71ae5a4SJacob Faibussowitsch       case 2:
4200d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4201d71ae5a4SJacob Faibussowitsch         break;
4202d71ae5a4SJacob Faibussowitsch       case 3:
4203d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4204d71ae5a4SJacob Faibussowitsch         break;
4205ba2698f1SMatthew G. Knepley       case 4:
4206ba2698f1SMatthew G. Knepley         switch (dim) {
4207d71ae5a4SJacob Faibussowitsch         case 2:
4208d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4209d71ae5a4SJacob Faibussowitsch           break;
4210d71ae5a4SJacob Faibussowitsch         case 3:
4211d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4212d71ae5a4SJacob Faibussowitsch           break;
4213d71ae5a4SJacob Faibussowitsch         default:
4214d71ae5a4SJacob Faibussowitsch           break;
4215ba2698f1SMatthew G. Knepley         }
4216ba2698f1SMatthew G. Knepley         break;
4217d71ae5a4SJacob Faibussowitsch       case 5:
4218d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4219d71ae5a4SJacob Faibussowitsch         break;
4220d71ae5a4SJacob Faibussowitsch       case 6:
4221d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4222d71ae5a4SJacob Faibussowitsch         break;
4223d71ae5a4SJacob Faibussowitsch       case 8:
4224d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4225d71ae5a4SJacob Faibussowitsch         break;
4226d71ae5a4SJacob Faibussowitsch       default:
4227d71ae5a4SJacob Faibussowitsch         break;
4228ba2698f1SMatthew G. Knepley       }
4229ba2698f1SMatthew G. Knepley     }
4230ba2698f1SMatthew G. Knepley   } else {
4231ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4232ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4233ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4234ba2698f1SMatthew G. Knepley       switch (dim) {
4235ba2698f1SMatthew G. Knepley       case 1:
4236ba2698f1SMatthew G. Knepley         switch (coneSize) {
4237d71ae5a4SJacob Faibussowitsch         case 2:
4238d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4239d71ae5a4SJacob Faibussowitsch           break;
4240d71ae5a4SJacob Faibussowitsch         default:
4241d71ae5a4SJacob Faibussowitsch           break;
4242ba2698f1SMatthew G. Knepley         }
4243ba2698f1SMatthew G. Knepley         break;
4244ba2698f1SMatthew G. Knepley       case 2:
4245ba2698f1SMatthew G. Knepley         switch (coneSize) {
4246d71ae5a4SJacob Faibussowitsch         case 3:
4247d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4248d71ae5a4SJacob Faibussowitsch           break;
4249d71ae5a4SJacob Faibussowitsch         case 4:
4250d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4251d71ae5a4SJacob Faibussowitsch           break;
4252d71ae5a4SJacob Faibussowitsch         default:
4253d71ae5a4SJacob Faibussowitsch           break;
4254ba2698f1SMatthew G. Knepley         }
4255ba2698f1SMatthew G. Knepley         break;
4256ba2698f1SMatthew G. Knepley       case 3:
4257ba2698f1SMatthew G. Knepley         switch (coneSize) {
4258d71ae5a4SJacob Faibussowitsch         case 4:
4259d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4260d71ae5a4SJacob Faibussowitsch           break;
42619371c9d4SSatish Balay         case 5: {
4262da9060c4SMatthew G. Knepley           const PetscInt *cone;
4263da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4264da9060c4SMatthew G. Knepley 
42659566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
42669566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4267da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4268d71ae5a4SJacob Faibussowitsch           case 3:
4269d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4270d71ae5a4SJacob Faibussowitsch             break;
4271d71ae5a4SJacob Faibussowitsch           case 4:
4272d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4273d71ae5a4SJacob Faibussowitsch             break;
4274da9060c4SMatthew G. Knepley           }
42759371c9d4SSatish Balay         } break;
4276d71ae5a4SJacob Faibussowitsch         case 6:
4277d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4278d71ae5a4SJacob Faibussowitsch           break;
4279d71ae5a4SJacob Faibussowitsch         default:
4280d71ae5a4SJacob Faibussowitsch           break;
4281ba2698f1SMatthew G. Knepley         }
4282ba2698f1SMatthew G. Knepley         break;
4283d71ae5a4SJacob Faibussowitsch       default:
4284d71ae5a4SJacob Faibussowitsch         break;
4285ba2698f1SMatthew G. Knepley       }
4286ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4287ba2698f1SMatthew G. Knepley       switch (coneSize) {
4288d71ae5a4SJacob Faibussowitsch       case 2:
4289d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4290d71ae5a4SJacob Faibussowitsch         break;
4291d71ae5a4SJacob Faibussowitsch       case 3:
4292d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4293d71ae5a4SJacob Faibussowitsch         break;
4294d71ae5a4SJacob Faibussowitsch       case 4:
4295d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4296d71ae5a4SJacob Faibussowitsch         break;
4297d71ae5a4SJacob Faibussowitsch       default:
4298d71ae5a4SJacob Faibussowitsch         break;
4299ba2698f1SMatthew G. Knepley       }
4300ba2698f1SMatthew G. Knepley     }
4301ba2698f1SMatthew G. Knepley   }
4302412e9a14SMatthew G. Knepley   *pt = ct;
43033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4304ba2698f1SMatthew G. Knepley }
4305412e9a14SMatthew G. Knepley 
4306412e9a14SMatthew G. Knepley /*@
4307412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4308412e9a14SMatthew G. Knepley 
430920f4b53cSBarry Smith   Collective
4310412e9a14SMatthew G. Knepley 
4311412e9a14SMatthew G. Knepley   Input Parameter:
4312a1cb98faSBarry Smith . mesh - The `DMPLEX`
4313412e9a14SMatthew G. Knepley 
4314412e9a14SMatthew G. Knepley   Level: developer
4315412e9a14SMatthew G. Knepley 
4316a1cb98faSBarry Smith   Note:
4317a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4318a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4319a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4320412e9a14SMatthew G. Knepley 
4321a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4322a1cb98faSBarry Smith 
43231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4324412e9a14SMatthew G. Knepley @*/
4325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4326d71ae5a4SJacob Faibussowitsch {
4327412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4328412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4329412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4330412e9a14SMatthew G. Knepley 
4331412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4332412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4333412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
43349566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
43359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
43369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4337*21027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
4338*21027e53SStefano Zampini   PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
4339412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4340327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4341412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4342412e9a14SMatthew G. Knepley 
43439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
43449566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
434563a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
43469566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4347*21027e53SStefano Zampini     mesh->cellTypes[p - pStart].value_as_uint8 = ct;
4348412e9a14SMatthew G. Knepley   }
43499566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
43509566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
43513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4352ba2698f1SMatthew G. Knepley }
4353ba2698f1SMatthew G. Knepley 
4354552f7358SJed Brown /*@C
4355552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4356552f7358SJed Brown 
4357552f7358SJed Brown   Not Collective
4358552f7358SJed Brown 
4359552f7358SJed Brown   Input Parameters:
4360a1cb98faSBarry Smith + dm - The `DMPLEX` object
4361552f7358SJed Brown . numPoints - The number of input points for the join
4362552f7358SJed Brown - points - The input points
4363552f7358SJed Brown 
4364552f7358SJed Brown   Output Parameters:
4365552f7358SJed Brown + numCoveredPoints - The number of points in the join
4366552f7358SJed Brown - coveredPoints - The points in the join
4367552f7358SJed Brown 
4368552f7358SJed Brown   Level: intermediate
4369552f7358SJed Brown 
4370a1cb98faSBarry Smith   Note:
4371a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4372552f7358SJed Brown 
4373a1cb98faSBarry Smith   Fortran Note:
437420f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
43753813dfbdSMatthew G Knepley 
43761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4377552f7358SJed Brown @*/
4378d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4379d71ae5a4SJacob Faibussowitsch {
4380552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4381552f7358SJed Brown   PetscInt *join[2];
4382552f7358SJed Brown   PetscInt  joinSize, i = 0;
4383552f7358SJed Brown   PetscInt  dof, off, p, c, m;
43846302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4385552f7358SJed Brown 
4386552f7358SJed Brown   PetscFunctionBegin;
4387552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
438848bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
438948bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
439048bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
43916302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
43926302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
43936302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4394552f7358SJed Brown   /* Copy in support of first point */
43959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
43969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4397ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4398552f7358SJed Brown   /* Check each successive support */
4399552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4400552f7358SJed Brown     PetscInt newJoinSize = 0;
4401552f7358SJed Brown 
44029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
44039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4404552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4405552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4406552f7358SJed Brown 
4407552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4408552f7358SJed Brown         if (point == join[i][m]) {
4409552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4410552f7358SJed Brown           break;
4411552f7358SJed Brown         }
4412552f7358SJed Brown       }
4413552f7358SJed Brown     }
4414552f7358SJed Brown     joinSize = newJoinSize;
4415552f7358SJed Brown     i        = 1 - i;
4416552f7358SJed Brown   }
4417552f7358SJed Brown   *numCoveredPoints = joinSize;
4418552f7358SJed Brown   *coveredPoints    = join[i];
44196302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
44203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4421552f7358SJed Brown }
4422552f7358SJed Brown 
4423552f7358SJed Brown /*@C
4424552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4425552f7358SJed Brown 
4426552f7358SJed Brown   Not Collective
4427552f7358SJed Brown 
4428552f7358SJed Brown   Input Parameters:
4429a1cb98faSBarry Smith + dm - The `DMPLEX` object
4430552f7358SJed Brown . numPoints - The number of input points for the join
4431552f7358SJed Brown - points - The input points
4432552f7358SJed Brown 
4433552f7358SJed Brown   Output Parameters:
4434552f7358SJed Brown + numCoveredPoints - The number of points in the join
4435552f7358SJed Brown - coveredPoints - The points in the join
4436552f7358SJed Brown 
4437552f7358SJed Brown   Level: intermediate
4438552f7358SJed Brown 
4439a1cb98faSBarry Smith   Fortran Note:
444020f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4441a1cb98faSBarry Smith 
44421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4443552f7358SJed Brown @*/
4444d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4445d71ae5a4SJacob Faibussowitsch {
4446552f7358SJed Brown   PetscFunctionBegin;
4447552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4448d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4449d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4450d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
44519566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4452d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
44533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4454552f7358SJed Brown }
4455552f7358SJed Brown 
4456552f7358SJed Brown /*@C
4457552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4458552f7358SJed Brown 
4459552f7358SJed Brown   Not Collective
4460552f7358SJed Brown 
4461552f7358SJed Brown   Input Parameters:
4462a1cb98faSBarry Smith + dm - The `DMPLEX` object
4463552f7358SJed Brown . numPoints - The number of input points for the join
4464552f7358SJed Brown - points - The input points
4465552f7358SJed Brown 
4466552f7358SJed Brown   Output Parameters:
4467552f7358SJed Brown + numCoveredPoints - The number of points in the join
4468552f7358SJed Brown - coveredPoints - The points in the join
4469552f7358SJed Brown 
4470552f7358SJed Brown   Level: intermediate
4471552f7358SJed Brown 
4472a1cb98faSBarry Smith   Fortran Note:
447320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4474a1cb98faSBarry Smith 
44751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4476552f7358SJed Brown @*/
4477d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4478d71ae5a4SJacob Faibussowitsch {
4479552f7358SJed Brown   PetscInt *offsets, **closures;
4480552f7358SJed Brown   PetscInt *join[2];
4481552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
448224c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4483552f7358SJed Brown 
4484552f7358SJed Brown   PetscFunctionBegin;
4485552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
448648bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
448748bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
448848bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4489552f7358SJed Brown 
44909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
44919566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
44929566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
44936302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
449424c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
44959566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
44969566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4497552f7358SJed Brown 
4498552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4499552f7358SJed Brown     PetscInt closureSize;
4500552f7358SJed Brown 
45019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
45020d644c17SKarl Rupp 
4503552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4504552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4505552f7358SJed Brown       PetscInt pStart, pEnd, i;
4506552f7358SJed Brown 
45079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4508552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4509552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4510552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4511552f7358SJed Brown           break;
4512552f7358SJed Brown         }
4513552f7358SJed Brown       }
4514552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4515552f7358SJed Brown     }
451663a3b9bcSJacob 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);
4517552f7358SJed Brown   }
4518552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4519552f7358SJed Brown     PetscInt dof;
4520552f7358SJed Brown 
4521552f7358SJed Brown     /* Copy in support of first point */
4522552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4523ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4524552f7358SJed Brown     /* Check each successive cone */
4525552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4526552f7358SJed Brown       PetscInt newJoinSize = 0;
4527552f7358SJed Brown 
4528552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4529552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4530552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4531552f7358SJed Brown 
4532552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4533552f7358SJed Brown           if (point == join[i][m]) {
4534552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4535552f7358SJed Brown             break;
4536552f7358SJed Brown           }
4537552f7358SJed Brown         }
4538552f7358SJed Brown       }
4539552f7358SJed Brown       joinSize = newJoinSize;
4540552f7358SJed Brown       i        = 1 - i;
4541552f7358SJed Brown     }
4542552f7358SJed Brown     if (joinSize) break;
4543552f7358SJed Brown   }
4544552f7358SJed Brown   *numCoveredPoints = joinSize;
4545552f7358SJed Brown   *coveredPoints    = join[i];
454648a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
45479566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45489566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
45496302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
45503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4551552f7358SJed Brown }
4552552f7358SJed Brown 
4553552f7358SJed Brown /*@C
4554552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4555552f7358SJed Brown 
4556552f7358SJed Brown   Not Collective
4557552f7358SJed Brown 
4558552f7358SJed Brown   Input Parameters:
4559a1cb98faSBarry Smith + dm - The `DMPLEX` object
4560552f7358SJed Brown . numPoints - The number of input points for the meet
4561552f7358SJed Brown - points - The input points
4562552f7358SJed Brown 
4563552f7358SJed Brown   Output Parameters:
4564552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4565552f7358SJed Brown - coveredPoints - The points in the meet
4566552f7358SJed Brown 
4567552f7358SJed Brown   Level: intermediate
4568552f7358SJed Brown 
4569a1cb98faSBarry Smith   Note:
4570a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4571552f7358SJed Brown 
45723813dfbdSMatthew G Knepley   Fortran Notes:
457320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
45743813dfbdSMatthew G Knepley 
45751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4576552f7358SJed Brown @*/
4577d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4578d71ae5a4SJacob Faibussowitsch {
4579552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4580552f7358SJed Brown   PetscInt *meet[2];
4581552f7358SJed Brown   PetscInt  meetSize, i = 0;
4582552f7358SJed Brown   PetscInt  dof, off, p, c, m;
45836302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4584552f7358SJed Brown 
4585552f7358SJed Brown   PetscFunctionBegin;
4586552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4587dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4588dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4589064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
45906302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
45916302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
45926302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4593552f7358SJed Brown   /* Copy in cone of first point */
45949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
45959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4596ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4597552f7358SJed Brown   /* Check each successive cone */
4598552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4599552f7358SJed Brown     PetscInt newMeetSize = 0;
4600552f7358SJed Brown 
46019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
46029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4603552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4604552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4605552f7358SJed Brown 
4606552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4607552f7358SJed Brown         if (point == meet[i][m]) {
4608552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4609552f7358SJed Brown           break;
4610552f7358SJed Brown         }
4611552f7358SJed Brown       }
4612552f7358SJed Brown     }
4613552f7358SJed Brown     meetSize = newMeetSize;
4614552f7358SJed Brown     i        = 1 - i;
4615552f7358SJed Brown   }
4616552f7358SJed Brown   *numCoveringPoints = meetSize;
4617552f7358SJed Brown   *coveringPoints    = meet[i];
46186302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
46193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4620552f7358SJed Brown }
4621552f7358SJed Brown 
4622552f7358SJed Brown /*@C
4623552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4624552f7358SJed Brown 
4625552f7358SJed Brown   Not Collective
4626552f7358SJed Brown 
4627552f7358SJed Brown   Input Parameters:
4628a1cb98faSBarry Smith + dm - The `DMPLEX` object
4629552f7358SJed Brown . numPoints - The number of input points for the meet
4630552f7358SJed Brown - points - The input points
4631552f7358SJed Brown 
4632552f7358SJed Brown   Output Parameters:
4633552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4634552f7358SJed Brown - coveredPoints - The points in the meet
4635552f7358SJed Brown 
4636552f7358SJed Brown   Level: intermediate
4637552f7358SJed Brown 
4638a1cb98faSBarry Smith   Fortran Note:
463920f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46403813dfbdSMatthew G Knepley 
46411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4642552f7358SJed Brown @*/
4643d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4644d71ae5a4SJacob Faibussowitsch {
4645552f7358SJed Brown   PetscFunctionBegin;
4646552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4647d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4648d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4649d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
46509566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4651d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
46523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4653552f7358SJed Brown }
4654552f7358SJed Brown 
4655552f7358SJed Brown /*@C
4656552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4657552f7358SJed Brown 
4658552f7358SJed Brown   Not Collective
4659552f7358SJed Brown 
4660552f7358SJed Brown   Input Parameters:
4661a1cb98faSBarry Smith + dm - The `DMPLEX` object
4662552f7358SJed Brown . numPoints - The number of input points for the meet
4663552f7358SJed Brown - points - The input points
4664552f7358SJed Brown 
4665552f7358SJed Brown   Output Parameters:
4666552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4667552f7358SJed Brown - coveredPoints - The points in the meet
4668552f7358SJed Brown 
4669552f7358SJed Brown   Level: intermediate
4670552f7358SJed Brown 
4671a1cb98faSBarry Smith   Fortran Note:
467220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46733813dfbdSMatthew G Knepley 
46741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4675552f7358SJed Brown @*/
4676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4677d71ae5a4SJacob Faibussowitsch {
4678552f7358SJed Brown   PetscInt *offsets, **closures;
4679552f7358SJed Brown   PetscInt *meet[2];
4680552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
468124c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4682552f7358SJed Brown 
4683552f7358SJed Brown   PetscFunctionBegin;
4684552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4685dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4686dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4687064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4688552f7358SJed Brown 
46899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
46909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
46919566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
46926302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
469324c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
46949566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
46959566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4696552f7358SJed Brown 
4697552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4698552f7358SJed Brown     PetscInt closureSize;
4699552f7358SJed Brown 
47009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
47010d644c17SKarl Rupp 
4702552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4703552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4704552f7358SJed Brown       PetscInt pStart, pEnd, i;
4705552f7358SJed Brown 
47069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4707552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4708552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4709552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4710552f7358SJed Brown           break;
4711552f7358SJed Brown         }
4712552f7358SJed Brown       }
4713552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4714552f7358SJed Brown     }
471563a3b9bcSJacob 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);
4716552f7358SJed Brown   }
4717552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4718552f7358SJed Brown     PetscInt dof;
4719552f7358SJed Brown 
4720552f7358SJed Brown     /* Copy in cone of first point */
4721552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
4722ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
4723552f7358SJed Brown     /* Check each successive cone */
4724552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4725552f7358SJed Brown       PetscInt newMeetSize = 0;
4726552f7358SJed Brown 
4727552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
4728552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4729552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
4730552f7358SJed Brown 
4731552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4732552f7358SJed Brown           if (point == meet[i][m]) {
4733552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
4734552f7358SJed Brown             break;
4735552f7358SJed Brown           }
4736552f7358SJed Brown         }
4737552f7358SJed Brown       }
4738552f7358SJed Brown       meetSize = newMeetSize;
4739552f7358SJed Brown       i        = 1 - i;
4740552f7358SJed Brown     }
4741552f7358SJed Brown     if (meetSize) break;
4742552f7358SJed Brown   }
4743552f7358SJed Brown   *numCoveredPoints = meetSize;
4744552f7358SJed Brown   *coveredPoints    = meet[i];
474548a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
47469566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
47479566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
47486302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
47493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4750552f7358SJed Brown }
4751552f7358SJed Brown 
47524e3744c5SMatthew G. Knepley /*@C
4753a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
47544e3744c5SMatthew G. Knepley 
47554e3744c5SMatthew G. Knepley   Not Collective
47564e3744c5SMatthew G. Knepley 
47574e3744c5SMatthew G. Knepley   Input Parameters:
4758a1cb98faSBarry Smith + dmA - A `DMPLEX` object
4759a1cb98faSBarry Smith - dmB - A `DMPLEX` object
47604e3744c5SMatthew G. Knepley 
47612fe279fdSBarry Smith   Output Parameter:
4762a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
47634e3744c5SMatthew G. Knepley 
47644e3744c5SMatthew G. Knepley   Level: intermediate
47654e3744c5SMatthew G. Knepley 
4766a1cb98faSBarry Smith   Note:
47673c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
47684e3744c5SMatthew G. Knepley 
47691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
47704e3744c5SMatthew G. Knepley @*/
4771d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
4772d71ae5a4SJacob Faibussowitsch {
47734e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
47744e3744c5SMatthew G. Knepley 
47754e3744c5SMatthew G. Knepley   PetscFunctionBegin;
47764e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
47774e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4778dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
47794e3744c5SMatthew G. Knepley 
47804e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
47819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
47829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
47833ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
47849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
47859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
47863ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
47874e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
47884e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
47894e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
47904e3744c5SMatthew G. Knepley 
47919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
47929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
47939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
47949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
47959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
47969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
47973ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
47984e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
47993ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
48003ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
48014e3744c5SMatthew G. Knepley     }
48029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
48039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
48049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
48059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
48063ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
48074e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
48083ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
48094e3744c5SMatthew G. Knepley     }
48104e3744c5SMatthew G. Knepley   }
48114e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
48123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48134e3744c5SMatthew G. Knepley }
48144e3744c5SMatthew G. Knepley 
48157cd05799SMatthew G. Knepley /*@C
48167cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
48177cd05799SMatthew G. Knepley 
48187cd05799SMatthew G. Knepley   Not Collective
48197cd05799SMatthew G. Knepley 
48207cd05799SMatthew G. Knepley   Input Parameters:
4821a1cb98faSBarry Smith + dm         - The `DMPLEX`
48227cd05799SMatthew G. Knepley . cellDim    - The cell dimension
48237cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
48247cd05799SMatthew G. Knepley 
48252fe279fdSBarry Smith   Output Parameter:
48267cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
48277cd05799SMatthew G. Knepley 
48287cd05799SMatthew G. Knepley   Level: developer
48297cd05799SMatthew G. Knepley 
4830a1cb98faSBarry Smith   Note:
48317cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
48327cd05799SMatthew G. Knepley 
48331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
48347cd05799SMatthew G. Knepley @*/
4835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4836d71ae5a4SJacob Faibussowitsch {
483782f516ccSBarry Smith   MPI_Comm comm;
4838552f7358SJed Brown 
4839552f7358SJed Brown   PetscFunctionBegin;
48409566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4841dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices, 4);
4842552f7358SJed Brown   switch (cellDim) {
4843d71ae5a4SJacob Faibussowitsch   case 0:
4844d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
4845d71ae5a4SJacob Faibussowitsch     break;
4846d71ae5a4SJacob Faibussowitsch   case 1:
4847d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
4848d71ae5a4SJacob Faibussowitsch     break;
4849552f7358SJed Brown   case 2:
4850552f7358SJed Brown     switch (numCorners) {
485119436ca2SJed Brown     case 3:                 /* triangle */
485219436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4853552f7358SJed Brown       break;
485419436ca2SJed Brown     case 4:                 /* quadrilateral */
485519436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4856552f7358SJed Brown       break;
485719436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
485819436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4859552f7358SJed Brown       break;
486019436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
486119436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4862552f7358SJed Brown       break;
4863d71ae5a4SJacob Faibussowitsch     default:
4864d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4865552f7358SJed Brown     }
4866552f7358SJed Brown     break;
4867552f7358SJed Brown   case 3:
4868552f7358SJed Brown     switch (numCorners) {
486919436ca2SJed Brown     case 4:                 /* tetradehdron */
487019436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4871552f7358SJed Brown       break;
487219436ca2SJed Brown     case 6:                 /* tet cohesive cells */
487319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4874552f7358SJed Brown       break;
487519436ca2SJed Brown     case 8:                 /* hexahedron */
487619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4877552f7358SJed Brown       break;
487819436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
487919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4880552f7358SJed Brown       break;
488119436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
488219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4883552f7358SJed Brown       break;
488419436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
488519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4886552f7358SJed Brown       break;
488719436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
488819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4889552f7358SJed Brown       break;
489019436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
489119436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4892552f7358SJed Brown       break;
4893d71ae5a4SJacob Faibussowitsch     default:
4894d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4895552f7358SJed Brown     }
4896552f7358SJed Brown     break;
4897d71ae5a4SJacob Faibussowitsch   default:
4898d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4899552f7358SJed Brown   }
49003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4901552f7358SJed Brown }
4902552f7358SJed Brown 
4903552f7358SJed Brown /*@
4904a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
4905552f7358SJed Brown 
4906552f7358SJed Brown   Not Collective
4907552f7358SJed Brown 
4908aa50250dSMatthew G. Knepley   Input Parameter:
4909a1cb98faSBarry Smith . dm    - The `DMPLEX` object
4910552f7358SJed Brown 
4911aa50250dSMatthew G. Knepley   Output Parameter:
4912a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
4913552f7358SJed Brown 
4914552f7358SJed Brown   Level: developer
4915552f7358SJed Brown 
49161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4917aa50250dSMatthew G. Knepley @*/
4918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4919d71ae5a4SJacob Faibussowitsch {
4920aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4921aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4922aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4923c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
49243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4925aa50250dSMatthew G. Knepley }
4926aa50250dSMatthew G. Knepley 
4927aa50250dSMatthew G. Knepley /*@
4928aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4929aa50250dSMatthew G. Knepley 
4930aa50250dSMatthew G. Knepley   Not Collective
4931aa50250dSMatthew G. Knepley 
4932aa50250dSMatthew G. Knepley   Input Parameter:
4933a1cb98faSBarry Smith . dm    - The `DMPLEX` object
4934aa50250dSMatthew G. Knepley 
4935aa50250dSMatthew G. Knepley   Output Parameter:
4936aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4937aa50250dSMatthew G. Knepley 
4938aa50250dSMatthew G. Knepley   Level: developer
4939552f7358SJed Brown 
4940b1bb481bSMatthew Knepley   Notes:
4941a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
4942a1cb98faSBarry Smith 
4943a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
4944a1cb98faSBarry Smith 
4945dc287ab2SVaclav Hapla   An empty mesh gives -1.
4946b1bb481bSMatthew Knepley 
49471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4948552f7358SJed Brown @*/
4949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4950d71ae5a4SJacob Faibussowitsch {
49519f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4952aa50250dSMatthew G. Knepley   DMLabel  label;
4953aa50250dSMatthew G. Knepley   PetscInt d = 0;
4954552f7358SJed Brown 
4955552f7358SJed Brown   PetscFunctionBegin;
4956552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4957dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
49589f4ada15SMatthew G. Knepley   if (mesh->tr) {
49599f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
49609f4ada15SMatthew G. Knepley   } else {
49619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
49629566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
4963552f7358SJed Brown     *depth = d - 1;
49649f4ada15SMatthew G. Knepley   }
49653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4966552f7358SJed Brown }
4967552f7358SJed Brown 
4968552f7358SJed Brown /*@
496920f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
4970552f7358SJed Brown 
4971552f7358SJed Brown   Not Collective
4972552f7358SJed Brown 
4973552f7358SJed Brown   Input Parameters:
4974a1cb98faSBarry Smith + dm    - The `DMPLEX` object
4975570fa34dSVaclav Hapla - depth - The requested depth
4976552f7358SJed Brown 
4977552f7358SJed Brown   Output Parameters:
497820f4b53cSBarry Smith + start - The first point at this `depth`
497920f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
4980552f7358SJed Brown 
4981552f7358SJed Brown   Level: developer
4982552f7358SJed Brown 
4983a1cb98faSBarry Smith   Notes:
4984a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4985a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
4986a1cb98faSBarry Smith   higher dimension, e.g., "edges".
4987a1cb98faSBarry Smith 
49881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4989552f7358SJed Brown @*/
4990d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
4991d71ae5a4SJacob Faibussowitsch {
49929f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4993aa50250dSMatthew G. Knepley   DMLabel  label;
499463d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
4995552f7358SJed Brown 
4996552f7358SJed Brown   PetscFunctionBegin;
4997552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49989371c9d4SSatish Balay   if (start) {
49999371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
50009371c9d4SSatish Balay     *start = 0;
50019371c9d4SSatish Balay   }
50029371c9d4SSatish Balay   if (end) {
50039371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
50049371c9d4SSatish Balay     *end = 0;
50059371c9d4SSatish Balay   }
50069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
50073ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5008570fa34dSVaclav Hapla   if (depth < 0) {
500963d1a920SMatthew G. Knepley     if (start) *start = pStart;
501063d1a920SMatthew G. Knepley     if (end) *end = pEnd;
50113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5012552f7358SJed Brown   }
50139f4ada15SMatthew G. Knepley   if (mesh->tr) {
50149f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
50159f4ada15SMatthew G. Knepley   } else {
50169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
501728b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5018570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
50199f4ada15SMatthew G. Knepley   }
50203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5021552f7358SJed Brown }
5022552f7358SJed Brown 
5023552f7358SJed Brown /*@
502420f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5025552f7358SJed Brown 
5026552f7358SJed Brown   Not Collective
5027552f7358SJed Brown 
5028552f7358SJed Brown   Input Parameters:
5029a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5030570fa34dSVaclav Hapla - height - The requested height
5031552f7358SJed Brown 
5032552f7358SJed Brown   Output Parameters:
503320f4b53cSBarry Smith + start - The first point at this `height`
503420f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5035552f7358SJed Brown 
5036552f7358SJed Brown   Level: developer
5037552f7358SJed Brown 
5038a1cb98faSBarry Smith   Notes:
5039a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5040a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5041a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5042a1cb98faSBarry Smith 
50431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5044552f7358SJed Brown @*/
5045d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5046d71ae5a4SJacob Faibussowitsch {
5047aa50250dSMatthew G. Knepley   DMLabel  label;
504863d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5049552f7358SJed Brown 
5050552f7358SJed Brown   PetscFunctionBegin;
5051552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50529371c9d4SSatish Balay   if (start) {
50539371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
50549371c9d4SSatish Balay     *start = 0;
50559371c9d4SSatish Balay   }
50569371c9d4SSatish Balay   if (end) {
50579371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
50589371c9d4SSatish Balay     *end = 0;
50599371c9d4SSatish Balay   }
50609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
50613ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5062570fa34dSVaclav Hapla   if (height < 0) {
506363d1a920SMatthew G. Knepley     if (start) *start = pStart;
506463d1a920SMatthew G. Knepley     if (end) *end = pEnd;
50653ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5066552f7358SJed Brown   }
50679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
506828b400f6SJacob Faibussowitsch   PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
50699566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
5070570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth - 1 - height, start, end));
50713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5072552f7358SJed Brown }
5073552f7358SJed Brown 
5074ba2698f1SMatthew G. Knepley /*@
507520f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5076ba2698f1SMatthew G. Knepley 
5077ba2698f1SMatthew G. Knepley   Not Collective
5078ba2698f1SMatthew G. Knepley 
5079d8d19677SJose E. Roman   Input Parameters:
5080a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5081ba2698f1SMatthew G. Knepley - point - The point
5082ba2698f1SMatthew G. Knepley 
5083ba2698f1SMatthew G. Knepley   Output Parameter:
508420f4b53cSBarry Smith . depth - The depth of the `point`
5085ba2698f1SMatthew G. Knepley 
5086ba2698f1SMatthew G. Knepley   Level: intermediate
5087ba2698f1SMatthew G. Knepley 
50881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5089ba2698f1SMatthew G. Knepley @*/
5090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5091d71ae5a4SJacob Faibussowitsch {
5092ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5093ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
509440a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
50959566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
50963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5097ba2698f1SMatthew G. Knepley }
5098ba2698f1SMatthew G. Knepley 
5099ba2698f1SMatthew G. Knepley /*@
510020f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
51010c0a32dcSVaclav Hapla 
51020c0a32dcSVaclav Hapla   Not Collective
51030c0a32dcSVaclav Hapla 
5104d8d19677SJose E. Roman   Input Parameters:
5105a1cb98faSBarry Smith + dm    - The `DMPLEX` object
51060c0a32dcSVaclav Hapla - point - The point
51070c0a32dcSVaclav Hapla 
51080c0a32dcSVaclav Hapla   Output Parameter:
510920f4b53cSBarry Smith . height - The height of the `point`
51100c0a32dcSVaclav Hapla 
51110c0a32dcSVaclav Hapla   Level: intermediate
51120c0a32dcSVaclav Hapla 
51131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
51140c0a32dcSVaclav Hapla @*/
5115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5116d71ae5a4SJacob Faibussowitsch {
51170c0a32dcSVaclav Hapla   PetscInt n, pDepth;
51180c0a32dcSVaclav Hapla 
51190c0a32dcSVaclav Hapla   PetscFunctionBegin;
51200c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51210c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
51229566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
51239566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
51240c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
51253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51260c0a32dcSVaclav Hapla }
51270c0a32dcSVaclav Hapla 
51280c0a32dcSVaclav Hapla /*@
5129a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5130ba2698f1SMatthew G. Knepley 
5131ba2698f1SMatthew G. Knepley   Not Collective
5132ba2698f1SMatthew G. Knepley 
5133ba2698f1SMatthew G. Knepley   Input Parameter:
5134a1cb98faSBarry Smith . dm - The `DMPLEX` object
5135ba2698f1SMatthew G. Knepley 
5136ba2698f1SMatthew G. Knepley   Output Parameter:
5137a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5138412e9a14SMatthew G. Knepley 
5139ba2698f1SMatthew G. Knepley   Level: developer
5140ba2698f1SMatthew G. Knepley 
5141a1cb98faSBarry Smith   Note:
5142a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5143a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5144a1cb98faSBarry Smith 
51451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5146ba2698f1SMatthew G. Knepley @*/
5147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5148d71ae5a4SJacob Faibussowitsch {
5149ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5150ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5151ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
51529566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5153ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
51543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5155ba2698f1SMatthew G. Knepley }
5156ba2698f1SMatthew G. Knepley 
5157ba2698f1SMatthew G. Knepley /*@
5158ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5159ba2698f1SMatthew G. Knepley 
5160ba2698f1SMatthew G. Knepley   Not Collective
5161ba2698f1SMatthew G. Knepley 
5162d8d19677SJose E. Roman   Input Parameters:
5163a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5164ba2698f1SMatthew G. Knepley - cell - The cell
5165ba2698f1SMatthew G. Knepley 
5166ba2698f1SMatthew G. Knepley   Output Parameter:
5167ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5168ba2698f1SMatthew G. Knepley 
5169ba2698f1SMatthew G. Knepley   Level: intermediate
5170ba2698f1SMatthew G. Knepley 
51711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5172ba2698f1SMatthew G. Knepley @*/
5173d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5174d71ae5a4SJacob Faibussowitsch {
51759f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5176ba2698f1SMatthew G. Knepley   DMLabel  label;
5177ba2698f1SMatthew G. Knepley   PetscInt ct;
5178ba2698f1SMatthew G. Knepley 
5179ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5180ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5181ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
51829f4ada15SMatthew G. Knepley   if (mesh->tr) {
51839f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
51849f4ada15SMatthew G. Knepley   } else {
5185*21027e53SStefano Zampini     PetscInt pStart, pEnd;
5186*21027e53SStefano Zampini 
5187*21027e53SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL));
5188*21027e53SStefano Zampini     if (!mesh->cellTypes) { /* XXX remove? optimize? */
5189*21027e53SStefano Zampini       PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd));
5190*21027e53SStefano Zampini       PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
5191*21027e53SStefano Zampini       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
5192*21027e53SStefano Zampini       for (PetscInt p = pStart; p < pEnd; p++) {
5193*21027e53SStefano Zampini         PetscCall(DMLabelGetValue(label, p, &ct));
5194*21027e53SStefano Zampini         mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct;
5195*21027e53SStefano Zampini       }
5196*21027e53SStefano Zampini     }
5197*21027e53SStefano Zampini     *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8;
5198*21027e53SStefano Zampini     if (PetscDefined(USE_DEBUG)) {
51999566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
52009566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, cell, &ct));
520163a3b9bcSJacob Faibussowitsch       PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5202*21027e53SStefano Zampini       PetscCheck(ct == *celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct);
5203*21027e53SStefano Zampini     }
52049f4ada15SMatthew G. Knepley   }
52053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5206ba2698f1SMatthew G. Knepley }
5207ba2698f1SMatthew G. Knepley 
5208412e9a14SMatthew G. Knepley /*@
5209412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5210412e9a14SMatthew G. Knepley 
5211412e9a14SMatthew G. Knepley   Not Collective
5212412e9a14SMatthew G. Knepley 
5213412e9a14SMatthew G. Knepley   Input Parameters:
5214a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5215412e9a14SMatthew G. Knepley . cell - The cell
5216412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5217412e9a14SMatthew G. Knepley 
5218a1cb98faSBarry Smith   Level: advanced
5219a1cb98faSBarry Smith 
5220a1cb98faSBarry Smith   Note:
5221a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5222412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5223412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5224db485b19SStefano Zampini   DMCreateLabel(dm, "celltype") before getting or setting any cell types.
5225412e9a14SMatthew G. Knepley 
52261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5227412e9a14SMatthew G. Knepley @*/
5228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5229d71ae5a4SJacob Faibussowitsch {
5230*21027e53SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
5231412e9a14SMatthew G. Knepley   DMLabel  label;
5232*21027e53SStefano Zampini   PetscInt pStart, pEnd;
5233412e9a14SMatthew G. Knepley 
5234412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5235412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5236*21027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
52379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
52389566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
5239*21027e53SStefano Zampini   if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
5240*21027e53SStefano Zampini   mesh->cellTypes[cell - pStart].value_as_uint8 = celltype;
52413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5242412e9a14SMatthew G. Knepley }
5243412e9a14SMatthew G. Knepley 
5244d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5245d71ae5a4SJacob Faibussowitsch {
5246efe440bfSMatthew G. Knepley   PetscSection section, s;
5247efe440bfSMatthew G. Knepley   Mat          m;
52483e922f36SToby Isaac   PetscInt     maxHeight;
5249dd4c3f67SMatthew G. Knepley   const char  *prefix;
5250552f7358SJed Brown 
5251552f7358SJed Brown   PetscFunctionBegin;
52529566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5253dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5254dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5255dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
52569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
52579566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
52589566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
52599566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
52609566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
52619566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
52629566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
52639566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
52649566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
52659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
52668f4c458bSMatthew G. Knepley 
52679566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
52689566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5269dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5270dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
52713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5272552f7358SJed Brown }
5273552f7358SJed Brown 
5274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5275d71ae5a4SJacob Faibussowitsch {
52766858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
52776858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5278f19dbd58SToby Isaac 
5279f19dbd58SToby Isaac   PetscFunctionBegin;
5280f19dbd58SToby Isaac   *field = NULL;
52819566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
52829566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
52836858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
52846858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5285f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
52866858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
52876858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5288f19dbd58SToby Isaac   }
52893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5290f19dbd58SToby Isaac }
5291f19dbd58SToby Isaac 
52927cd05799SMatthew G. Knepley /*@C
52937cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
52947cd05799SMatthew G. Knepley 
52957cd05799SMatthew G. Knepley   Not Collective
52967cd05799SMatthew G. Knepley 
52972fe279fdSBarry Smith   Input Parameter:
5298a1cb98faSBarry Smith . dm        - The `DMPLEX` object
52997cd05799SMatthew G. Knepley 
53007cd05799SMatthew G. Knepley   Output Parameter:
5301a1cb98faSBarry Smith . section - The `PetscSection` object
53027cd05799SMatthew G. Knepley 
53037cd05799SMatthew G. Knepley   Level: developer
53047cd05799SMatthew G. Knepley 
53051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
53067cd05799SMatthew G. Knepley @*/
5307d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5308d71ae5a4SJacob Faibussowitsch {
5309552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5310552f7358SJed Brown 
5311552f7358SJed Brown   PetscFunctionBegin;
5312552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5313552f7358SJed Brown   if (section) *section = mesh->coneSection;
53143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5315552f7358SJed Brown }
5316552f7358SJed Brown 
53177cd05799SMatthew G. Knepley /*@C
53187cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
53197cd05799SMatthew G. Knepley 
53207cd05799SMatthew G. Knepley   Not Collective
53217cd05799SMatthew G. Knepley 
53222fe279fdSBarry Smith   Input Parameter:
5323a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53247cd05799SMatthew G. Knepley 
53257cd05799SMatthew G. Knepley   Output Parameter:
5326a1cb98faSBarry Smith . section - The `PetscSection` object
53277cd05799SMatthew G. Knepley 
53287cd05799SMatthew G. Knepley   Level: developer
53297cd05799SMatthew G. Knepley 
53301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
53317cd05799SMatthew G. Knepley @*/
5332d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5333d71ae5a4SJacob Faibussowitsch {
53348cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
53358cb4d582SMatthew G. Knepley 
53368cb4d582SMatthew G. Knepley   PetscFunctionBegin;
53378cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53388cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
53393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53408cb4d582SMatthew G. Knepley }
53418cb4d582SMatthew G. Knepley 
53427cd05799SMatthew G. Knepley /*@C
53437cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
53447cd05799SMatthew G. Knepley 
53457cd05799SMatthew G. Knepley   Not Collective
53467cd05799SMatthew G. Knepley 
53472fe279fdSBarry Smith   Input Parameter:
5348a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53497cd05799SMatthew G. Knepley 
53507cd05799SMatthew G. Knepley   Output Parameter:
53517cd05799SMatthew G. Knepley . cones - The cone for each point
53527cd05799SMatthew G. Knepley 
53537cd05799SMatthew G. Knepley   Level: developer
53547cd05799SMatthew G. Knepley 
53551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
53567cd05799SMatthew G. Knepley @*/
5357d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5358d71ae5a4SJacob Faibussowitsch {
5359552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5360552f7358SJed Brown 
5361552f7358SJed Brown   PetscFunctionBegin;
5362552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5363552f7358SJed Brown   if (cones) *cones = mesh->cones;
53643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5365552f7358SJed Brown }
5366552f7358SJed Brown 
53677cd05799SMatthew G. Knepley /*@C
53687cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
53697cd05799SMatthew G. Knepley 
53707cd05799SMatthew G. Knepley   Not Collective
53717cd05799SMatthew G. Knepley 
53722fe279fdSBarry Smith   Input Parameter:
5373a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53747cd05799SMatthew G. Knepley 
53757cd05799SMatthew G. Knepley   Output Parameter:
5376b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
53777cd05799SMatthew G. Knepley 
53787cd05799SMatthew G. Knepley   Level: developer
53797cd05799SMatthew G. Knepley 
5380b5a892a1SMatthew G. Knepley   Notes:
5381a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5382b5a892a1SMatthew G. Knepley 
5383a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5384b5a892a1SMatthew G. Knepley 
53851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
53867cd05799SMatthew G. Knepley @*/
5387d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5388d71ae5a4SJacob Faibussowitsch {
5389552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5390552f7358SJed Brown 
5391552f7358SJed Brown   PetscFunctionBegin;
5392552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5393552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
53943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5395552f7358SJed Brown }
5396552f7358SJed Brown 
5397552f7358SJed Brown /******************************** FEM Support **********************************/
5398552f7358SJed Brown 
53999e8305c2SJed Brown /*
54009e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
54019e8305c2SJed Brown  representing a line in the section.
54029e8305c2SJed Brown */
5403d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k)
5404d71ae5a4SJacob Faibussowitsch {
54059e8305c2SJed Brown   PetscFunctionBeginHot;
54069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5407a433471fSStefano Zampini   if (line < 0) {
5408a433471fSStefano Zampini     *k  = 0;
5409a433471fSStefano Zampini     *Nc = 0;
5410a433471fSStefano Zampini   } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */
54119e8305c2SJed Brown     *k = 1;
54129e8305c2SJed Brown   } else { /* Assume the full interpolated mesh is in the chart; lines in particular */
54139e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
54149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
54159e8305c2SJed Brown     *k = *k / *Nc + 1;
54169e8305c2SJed Brown   }
54173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54189e8305c2SJed Brown }
54199e8305c2SJed Brown 
5420a4355906SMatthew Knepley /*@
5421bc1eb3faSJed Brown 
5422bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5423bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
542420f4b53cSBarry Smith   section provided (or the section of the `DM`).
5425a4355906SMatthew Knepley 
5426a4355906SMatthew Knepley   Input Parameters:
542720f4b53cSBarry Smith + dm      - The `DM`
542820f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
542920f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5430a4355906SMatthew Knepley 
5431bc1eb3faSJed Brown   Example:
5432bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5433bc1eb3faSJed Brown .vb
5434bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5435bc1eb3faSJed Brown 
5436bc1eb3faSJed Brown   v4 -- e6 -- v3
5437bc1eb3faSJed Brown   |           |
5438bc1eb3faSJed Brown   e7    c0    e8
5439bc1eb3faSJed Brown   |           |
5440bc1eb3faSJed Brown   v1 -- e5 -- v2
5441bc1eb3faSJed Brown .ve
5442bc1eb3faSJed Brown 
5443bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5444bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5445bc1eb3faSJed Brown .vb
5446bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5447bc1eb3faSJed Brown     v1 -> [4]
5448bc1eb3faSJed Brown     ...
5449bc1eb3faSJed Brown     e5 -> [8, 9]
5450bc1eb3faSJed Brown .ve
5451bc1eb3faSJed Brown 
5452bc1eb3faSJed Brown   which corresponds to the dofs
5453bc1eb3faSJed Brown .vb
5454bc1eb3faSJed Brown     6   10  11  7
5455bc1eb3faSJed Brown     13  2   3   15
5456bc1eb3faSJed Brown     12  0   1   14
5457bc1eb3faSJed Brown     4   8   9   5
5458bc1eb3faSJed Brown .ve
5459bc1eb3faSJed Brown 
5460bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5461bc1eb3faSJed Brown .vb
5462bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5463bc1eb3faSJed Brown .ve
5464bc1eb3faSJed Brown 
5465bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5466bc1eb3faSJed Brown .vb
5467bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5468bc1eb3faSJed Brown .ve
5469bc1eb3faSJed Brown 
5470a4355906SMatthew Knepley   Level: developer
5471a4355906SMatthew Knepley 
5472a1cb98faSBarry Smith   Note:
5473a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5474a1cb98faSBarry Smith   degree of the basis.
5475a1cb98faSBarry Smith 
54761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5477a4355906SMatthew Knepley @*/
5478d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5479d71ae5a4SJacob Faibussowitsch {
54807391a63aSMatthew G. Knepley   DMLabel   label;
5481bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
54829e8305c2SJed Brown   PetscBool vertexchart;
54833194fc30SMatthew G. Knepley 
54843194fc30SMatthew G. Knepley   PetscFunctionBegin;
54859566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
54863ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5487a433471fSStefano Zampini   if (point < 0) {
5488a433471fSStefano Zampini     PetscInt sStart, sEnd;
5489a433471fSStefano Zampini 
54909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5491a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5492a433471fSStefano Zampini   }
54939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
54949566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
54959566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
54969371c9d4SSatish Balay   if (depth == 1) {
54979371c9d4SSatish Balay     eStart = point;
54989371c9d4SSatish Balay   } else if (depth == dim) {
54997391a63aSMatthew G. Knepley     const PetscInt *cone;
55007391a63aSMatthew G. Knepley 
55019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5502d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5503d4e6627bSStefano Zampini     else if (dim == 3) {
5504d4e6627bSStefano Zampini       const PetscInt *cone2;
55059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5506d4e6627bSStefano Zampini       eStart = cone2[0];
550763a3b9bcSJacob 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);
550863a3b9bcSJacob 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);
55099e8305c2SJed Brown   { /* Determine whether the chart covers all points or just vertices. */
55109e8305c2SJed Brown     PetscInt pStart, pEnd, cStart, cEnd;
55119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd));
55129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section, &cStart, &cEnd));
5513796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5514796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5515796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
55169e8305c2SJed Brown   }
55179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5518bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5519bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5520bb197d40SJed Brown     PetscInt *perm;
5521bb197d40SJed Brown 
55223194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
55239566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5524bb197d40SJed Brown       size += PetscPowInt(k + 1, d) * Nc;
55253194fc30SMatthew G. Knepley     }
55269566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
55273194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5528bb197d40SJed Brown       switch (d) {
5529babf31e0SJed Brown       case 1:
55309566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5531babf31e0SJed Brown         /*
5532babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5533babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5534babf31e0SJed Brown          */
5535babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
55369371c9d4SSatish Balay         for (i = 0; i < k - 1; i++)
55379371c9d4SSatish Balay           for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5538babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5539babf31e0SJed Brown         foffset = offset;
5540babf31e0SJed Brown         break;
554189eabcffSMatthew G. Knepley       case 2:
55423194fc30SMatthew 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} */
55439566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
55443194fc30SMatthew G. Knepley         /* The SEM order is
55453194fc30SMatthew G. Knepley 
55463194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
554789eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
55483194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
55493194fc30SMatthew G. Knepley          */
55503194fc30SMatthew G. Knepley         {
55513194fc30SMatthew G. Knepley           const PetscInt of   = 0;
55523194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
55533194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
55543194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
55553194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
55563194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
55573194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
55583194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
55593194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
55603194fc30SMatthew G. Knepley           PetscInt       o;
55613194fc30SMatthew G. Knepley 
55623194fc30SMatthew G. Knepley           /* bottom */
55633194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
55649371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
55659371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55663194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
55673194fc30SMatthew G. Knepley           /* middle */
55683194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
55693194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
55709371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
55719371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55723194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
55733194fc30SMatthew G. Knepley           }
55743194fc30SMatthew G. Knepley           /* top */
55753194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
55769371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
55779371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55783194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
55793194fc30SMatthew G. Knepley           foffset = offset;
55803194fc30SMatthew G. Knepley         }
558189eabcffSMatthew G. Knepley         break;
558289eabcffSMatthew G. Knepley       case 3:
558389eabcffSMatthew G. Knepley         /* The original hex closure is
558489eabcffSMatthew G. Knepley 
558589eabcffSMatthew G. Knepley          {c,
558689eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
558789eabcffSMatthew 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,
558889eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
558989eabcffSMatthew G. Knepley          */
55909566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
559189eabcffSMatthew G. Knepley         /* The SEM order is
559289eabcffSMatthew G. Knepley          Bottom Slice
559389eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
559489eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
559589eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
559689eabcffSMatthew G. Knepley 
559789eabcffSMatthew G. Knepley          Middle Slice (j)
559889eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
559989eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
560089eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
560189eabcffSMatthew G. Knepley 
560289eabcffSMatthew G. Knepley          Top Slice
560389eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
560489eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
560589eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
560689eabcffSMatthew G. Knepley          */
560789eabcffSMatthew G. Knepley         {
560889eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
560989eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
561089eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
561189eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
561289eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
561389eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
561489eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
561589eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
561689eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
561789eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
561889eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
561989eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
562089eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
562189eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
562289eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
562389eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
562489eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
562589eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
562689eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
562789eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
562889eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
562989eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
563089eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
563189eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
563289eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
563389eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
563489eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
563589eabcffSMatthew G. Knepley           PetscInt       o, n;
563689eabcffSMatthew G. Knepley 
563789eabcffSMatthew G. Knepley           /* Bottom Slice */
563889eabcffSMatthew G. Knepley           /*   bottom */
563989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
56409371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
56419371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
564289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
564389eabcffSMatthew G. Knepley           /*   middle */
564489eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
564589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
56469371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
56479371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
56489371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56499371c9d4SSatish Balay             }
565089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
56513194fc30SMatthew G. Knepley           }
565289eabcffSMatthew G. Knepley           /*   top */
565389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
56549371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
56559371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
565689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
565789eabcffSMatthew G. Knepley 
565889eabcffSMatthew G. Knepley           /* Middle Slice */
565989eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
566089eabcffSMatthew G. Knepley             /*   bottom */
566189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
56629371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
56639371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
566489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
566589eabcffSMatthew G. Knepley             /*   middle */
566689eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
566789eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
56689371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
56699371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
567089eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
567189eabcffSMatthew G. Knepley             }
567289eabcffSMatthew G. Knepley             /*   top */
567389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
56749371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
56759371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
567689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
567789eabcffSMatthew G. Knepley           }
567889eabcffSMatthew G. Knepley 
567989eabcffSMatthew G. Knepley           /* Top Slice */
568089eabcffSMatthew G. Knepley           /*   bottom */
568189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
56829371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
56839371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
568489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
568589eabcffSMatthew G. Knepley           /*   middle */
568689eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
568789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
56889371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
56899371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
569089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
569189eabcffSMatthew G. Knepley           }
569289eabcffSMatthew G. Knepley           /*   top */
569389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
56949371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
56959371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
569689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
569789eabcffSMatthew G. Knepley 
569889eabcffSMatthew G. Knepley           foffset = offset;
569989eabcffSMatthew G. Knepley         }
570089eabcffSMatthew G. Knepley         break;
5701d71ae5a4SJacob Faibussowitsch       default:
5702d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
570389eabcffSMatthew G. Knepley       }
570489eabcffSMatthew G. Knepley     }
570563a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
57063194fc30SMatthew G. Knepley     /* Check permutation */
57073194fc30SMatthew G. Knepley     {
57083194fc30SMatthew G. Knepley       PetscInt *check;
57093194fc30SMatthew G. Knepley 
57109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
57111dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
57121dca8a05SBarry Smith         check[i] = -1;
57131dca8a05SBarry 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]);
57141dca8a05SBarry Smith       }
57153194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
57161dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
57179566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
57183194fc30SMatthew G. Knepley     }
57199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
5720a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5721a05c9aa3SJed Brown       PetscInt *loc_perm;
57229566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
5723a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
5724a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
5725a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
5726a05c9aa3SJed Brown       }
57279566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
5728a05c9aa3SJed Brown     }
5729bb197d40SJed Brown   }
57303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57313194fc30SMatthew G. Knepley }
57323194fc30SMatthew G. Knepley 
5733d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5734d71ae5a4SJacob Faibussowitsch {
5735e071409bSToby Isaac   PetscDS  prob;
5736e071409bSToby Isaac   PetscInt depth, Nf, h;
5737e071409bSToby Isaac   DMLabel  label;
5738e071409bSToby Isaac 
5739e071409bSToby Isaac   PetscFunctionBeginHot;
57409566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5741e071409bSToby Isaac   Nf      = prob->Nf;
5742e071409bSToby Isaac   label   = dm->depthLabel;
5743e071409bSToby Isaac   *dspace = NULL;
5744e071409bSToby Isaac   if (field < Nf) {
5745e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5746e071409bSToby Isaac 
5747e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5748e071409bSToby Isaac       PetscDualSpace dsp;
5749e071409bSToby Isaac 
57509566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
57519566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
57529566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
5753e071409bSToby Isaac       h = depth - 1 - h;
5754e071409bSToby Isaac       if (h) {
57559566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
5756e071409bSToby Isaac       } else {
5757e071409bSToby Isaac         *dspace = dsp;
5758e071409bSToby Isaac       }
5759e071409bSToby Isaac     }
5760e071409bSToby Isaac   }
57613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5762e071409bSToby Isaac }
5763e071409bSToby Isaac 
5764d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5765d71ae5a4SJacob Faibussowitsch {
576628351e22SJed Brown   PetscScalar       *array;
576728351e22SJed Brown   const PetscScalar *vArray;
5768d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
57691a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
5770552f7358SJed Brown 
57711b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
57729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
57739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
57749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
57759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
57763f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
57779df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
57789df71ca4SMatthew G. Knepley       PetscInt dof;
5779d9917b9dSMatthew G. Knepley 
57809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
57819df71ca4SMatthew G. Knepley       size += dof;
57829df71ca4SMatthew G. Knepley     }
57839df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
57849df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
57852a3aaacfSMatthew G. Knepley       PetscInt       dof;
57865a1bb5cfSMatthew G. Knepley 
57875a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
57889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
57895a1bb5cfSMatthew G. Knepley       size += dof;
57905a1bb5cfSMatthew G. Knepley     }
57913f7cbbe7SMatthew G. Knepley     if (!values) {
57923f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
57933ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
57943f7cbbe7SMatthew G. Knepley     }
57959566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5796982e9ed1SMatthew G. Knepley   } else {
5797982e9ed1SMatthew G. Knepley     array = *values;
5798982e9ed1SMatthew G. Knepley   }
57999df71ca4SMatthew G. Knepley   size = 0;
580028351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
58019df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
58029df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
580328351e22SJed Brown     const PetscScalar *varr;
5804d9917b9dSMatthew G. Knepley 
58059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
58069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
58079df71ca4SMatthew G. Knepley     varr = &vArray[off];
5808ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
58099df71ca4SMatthew G. Knepley     size += dof;
58109df71ca4SMatthew G. Knepley   }
58119df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
58129df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
58139df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
58145a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
581528351e22SJed Brown     const PetscScalar *varr;
58165a1bb5cfSMatthew G. Knepley 
581752ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
58189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
58199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
58205a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
58215a1bb5cfSMatthew G. Knepley     if (o >= 0) {
5822ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
58235a1bb5cfSMatthew G. Knepley     } else {
5824ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
58255a1bb5cfSMatthew G. Knepley     }
58269df71ca4SMatthew G. Knepley     size += dof;
58275a1bb5cfSMatthew G. Knepley   }
582828351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
58299df71ca4SMatthew G. Knepley   if (!*values) {
58305a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
58315a1bb5cfSMatthew G. Knepley     *values = array;
58329df71ca4SMatthew G. Knepley   } else {
583363a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
58348c312ff3SMatthew G. Knepley     *csize = size;
58359df71ca4SMatthew G. Knepley   }
58363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58375a1bb5cfSMatthew G. Knepley }
5838d9917b9dSMatthew G. Knepley 
583927f02ce8SMatthew G. Knepley /* Compress out points not in the section */
5840d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
5841d71ae5a4SJacob Faibussowitsch {
584227f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
584327f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
584427f02ce8SMatthew G. Knepley 
58459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
584627f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
584727f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
584827f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
584927f02ce8SMatthew G. Knepley       points[q * 2]     = r;
585027f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
585127f02ce8SMatthew G. Knepley       ++q;
585227f02ce8SMatthew G. Knepley     }
585327f02ce8SMatthew G. Knepley   }
585427f02ce8SMatthew G. Knepley   *numPoints = q;
58553ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
585627f02ce8SMatthew G. Knepley }
585727f02ce8SMatthew G. Knepley 
585897529cf3SJed Brown /* Compressed closure does not apply closure permutation */
585907218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5860d71ae5a4SJacob Faibussowitsch {
586127f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5862923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
5863923c78e0SToby Isaac 
5864923c78e0SToby Isaac   PetscFunctionBeginHot;
58659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
586607218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
5867923c78e0SToby Isaac     PetscInt dof, off;
5868923c78e0SToby Isaac 
58699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
58709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
58719566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5872923c78e0SToby Isaac     np  = dof / 2;
5873923c78e0SToby Isaac     pts = (PetscInt *)&cla[off];
587427f02ce8SMatthew G. Knepley   } else {
587507218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
58769566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5877923c78e0SToby Isaac   }
5878923c78e0SToby Isaac   *numPoints = np;
5879923c78e0SToby Isaac   *points    = pts;
5880923c78e0SToby Isaac   *clp       = cla;
58813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5882923c78e0SToby Isaac }
5883923c78e0SToby Isaac 
5884d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5885d71ae5a4SJacob Faibussowitsch {
5886923c78e0SToby Isaac   PetscFunctionBeginHot;
5887923c78e0SToby Isaac   if (!*clPoints) {
58889566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5889923c78e0SToby Isaac   } else {
58909566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5891923c78e0SToby Isaac   }
5892923c78e0SToby Isaac   *numPoints = 0;
5893923c78e0SToby Isaac   *points    = NULL;
5894923c78e0SToby Isaac   *clSec     = NULL;
5895923c78e0SToby Isaac   *clPoints  = NULL;
5896923c78e0SToby Isaac   *clp       = NULL;
58973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5898923c78e0SToby Isaac }
5899923c78e0SToby Isaac 
5900d71ae5a4SJacob 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[])
5901d71ae5a4SJacob Faibussowitsch {
59021a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
590397e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
590497e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
59051a271a75SMatthew G. Knepley 
59061a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5907fe02ba77SJed Brown   *size = 0;
59089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
590997e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
591097e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
591197e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
591297e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
59131a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
59141a271a75SMatthew G. Knepley     const PetscScalar *varr;
59151a271a75SMatthew G. Knepley 
59169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
59179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
59181a271a75SMatthew G. Knepley     varr = &vArray[off];
591997e99dd9SToby Isaac     if (clperm) {
592097e99dd9SToby Isaac       if (perm) {
592197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
59221a271a75SMatthew G. Knepley       } else {
592397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
592497e99dd9SToby Isaac       }
592597e99dd9SToby Isaac       if (flip) {
592697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
592797e99dd9SToby Isaac       }
592897e99dd9SToby Isaac     } else {
592997e99dd9SToby Isaac       if (perm) {
593097e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
593197e99dd9SToby Isaac       } else {
593297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
593397e99dd9SToby Isaac       }
593497e99dd9SToby Isaac       if (flip) {
593597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
59361a271a75SMatthew G. Knepley       }
59371a271a75SMatthew G. Knepley     }
593897e99dd9SToby Isaac     offset += dof;
593997e99dd9SToby Isaac   }
59409566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
59411a271a75SMatthew G. Knepley   *size = offset;
59423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59431a271a75SMatthew G. Knepley }
59441a271a75SMatthew G. Knepley 
5945d71ae5a4SJacob 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[])
5946d71ae5a4SJacob Faibussowitsch {
59471a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
59481a271a75SMatthew G. Knepley 
59491a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5950fe02ba77SJed Brown   *size = 0;
59511a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
595297e99dd9SToby Isaac     PetscInt            p;
595397e99dd9SToby Isaac     const PetscInt    **perms = NULL;
595497e99dd9SToby Isaac     const PetscScalar **flips = NULL;
59551a271a75SMatthew G. Knepley 
59569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
595797e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
595897e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
595997e99dd9SToby Isaac       PetscInt           fdof, foff, b;
59601a271a75SMatthew G. Knepley       const PetscScalar *varr;
596197e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
596297e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
59631a271a75SMatthew G. Knepley 
59649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
59659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
59661a271a75SMatthew G. Knepley       varr = &vArray[foff];
596797e99dd9SToby Isaac       if (clperm) {
59689371c9d4SSatish Balay         if (perm) {
5969ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
59701a271a75SMatthew G. Knepley         } else {
5971ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
59729371c9d4SSatish Balay         }
59739371c9d4SSatish Balay         if (flip) {
5974ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
59759371c9d4SSatish Balay         }
59769371c9d4SSatish Balay       } else {
59779371c9d4SSatish Balay         if (perm) {
5978ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
59799371c9d4SSatish Balay         } else {
5980ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
59819371c9d4SSatish Balay         }
59829371c9d4SSatish Balay         if (flip) {
5983ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
59849371c9d4SSatish Balay         }
59851a271a75SMatthew G. Knepley       }
598697e99dd9SToby Isaac       offset += fdof;
59871a271a75SMatthew G. Knepley     }
59889566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
59891a271a75SMatthew G. Knepley   }
59901a271a75SMatthew G. Knepley   *size = offset;
59913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59921a271a75SMatthew G. Knepley }
59931a271a75SMatthew G. Knepley 
599407218a29SMatthew G. Knepley PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
599507218a29SMatthew G. Knepley {
599607218a29SMatthew G. Knepley   PetscSection    clSection;
599707218a29SMatthew G. Knepley   IS              clPoints;
599807218a29SMatthew G. Knepley   PetscInt       *points = NULL;
599907218a29SMatthew G. Knepley   const PetscInt *clp, *perm;
600007218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
600107218a29SMatthew G. Knepley 
600207218a29SMatthew G. Knepley   PetscFunctionBeginHot;
600307218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
600407218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
600507218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
600607218a29SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
600707218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
600807218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
600907218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
601007218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
601107218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
601207218a29SMatthew G. Knepley   }
601307218a29SMatthew G. Knepley   /* Get points */
601407218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
601507218a29SMatthew G. Knepley   /* Get sizes */
601607218a29SMatthew G. Knepley   asize = 0;
601707218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
601807218a29SMatthew G. Knepley     PetscInt dof;
601907218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
602007218a29SMatthew G. Knepley     asize += dof;
602107218a29SMatthew G. Knepley   }
602207218a29SMatthew G. Knepley   if (values) {
602307218a29SMatthew G. Knepley     const PetscScalar *vArray;
602407218a29SMatthew G. Knepley     PetscInt           size;
602507218a29SMatthew G. Knepley 
602607218a29SMatthew G. Knepley     if (*values) {
602707218a29SMatthew 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);
602807218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
602907218a29SMatthew G. Knepley     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
603007218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
603107218a29SMatthew G. Knepley     /* Get values */
603207218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
603307218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
603407218a29SMatthew 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);
603507218a29SMatthew G. Knepley     /* Cleanup array */
603607218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
603707218a29SMatthew G. Knepley   }
603807218a29SMatthew G. Knepley   if (csize) *csize = asize;
603907218a29SMatthew G. Knepley   /* Cleanup points */
604007218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
604107218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
604207218a29SMatthew G. Knepley }
604307218a29SMatthew G. Knepley 
6044552f7358SJed Brown /*@C
6045552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6046552f7358SJed Brown 
6047552f7358SJed Brown   Not collective
6048552f7358SJed Brown 
6049552f7358SJed Brown   Input Parameters:
6050a1cb98faSBarry Smith + dm - The `DM`
605120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6052552f7358SJed Brown . v - The local vector
6053a1cb98faSBarry Smith - point - The point in the `DM`
6054552f7358SJed Brown 
60556b867d5aSJose E. Roman   Input/Output Parameters:
605620f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
605720f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
605820f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
605922c1ee49SMatthew G. Knepley 
6060552f7358SJed Brown   Level: intermediate
6061552f7358SJed Brown 
6062a1cb98faSBarry Smith   Notes:
606320f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6064a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6065a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6066a1cb98faSBarry Smith 
6067a1cb98faSBarry Smith   A typical use could be
6068a1cb98faSBarry Smith .vb
6069a1cb98faSBarry Smith    values = NULL;
6070a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6071a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6072a1cb98faSBarry Smith      <Compute on closure>
6073a1cb98faSBarry Smith    }
6074a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6075a1cb98faSBarry Smith .ve
6076a1cb98faSBarry Smith   or
6077a1cb98faSBarry Smith .vb
6078a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6079a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6080a1cb98faSBarry Smith      clSize = clMaxSize;
6081a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6082a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6083a1cb98faSBarry Smith        <Compute on closure>
6084a1cb98faSBarry Smith      }
6085a1cb98faSBarry Smith    }
6086a1cb98faSBarry Smith    PetscFree(values);
6087a1cb98faSBarry Smith .ve
6088a1cb98faSBarry Smith 
6089a1cb98faSBarry Smith   Fortran Note:
609020f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6091a1cb98faSBarry Smith 
60921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6093552f7358SJed Brown @*/
6094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6095d71ae5a4SJacob Faibussowitsch {
6096d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
609707218a29SMatthew G. Knepley   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, v, point, 0, csize, values));
60983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6099552f7358SJed Brown }
6100552f7358SJed Brown 
6101d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6102d71ae5a4SJacob Faibussowitsch {
6103e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6104e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6105e5c487bfSMatthew G. Knepley   IS                 clPoints;
6106e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6107e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6108e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6109c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6110c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6111e5c487bfSMatthew G. Knepley 
6112e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6113e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
61149566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6115e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6116e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
61179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
61189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
61199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6120e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
61219566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
61223ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6123e5c487bfSMatthew G. Knepley   }
6124e5c487bfSMatthew G. Knepley   /* Get points */
612507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6126c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6127c459fbc1SJed Brown     PetscInt dof;
61289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6129c459fbc1SJed Brown     clsize += dof;
6130c459fbc1SJed Brown   }
61319566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6132e5c487bfSMatthew G. Knepley   /* Filter points */
6133e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6134e5c487bfSMatthew G. Knepley     PetscInt dep;
6135e5c487bfSMatthew G. Knepley 
61369566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6137e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6138e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6139e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6140e5c487bfSMatthew G. Knepley     ++Np;
6141e5c487bfSMatthew G. Knepley   }
6142e5c487bfSMatthew G. Knepley   /* Get array */
6143e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6144e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6145e5c487bfSMatthew G. Knepley 
6146e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
61479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6148e5c487bfSMatthew G. Knepley       asize += dof;
6149e5c487bfSMatthew G. Knepley     }
6150e5c487bfSMatthew G. Knepley     if (!values) {
61519566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6152e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
61533ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6154e5c487bfSMatthew G. Knepley     }
61559566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6156e5c487bfSMatthew G. Knepley   } else {
6157e5c487bfSMatthew G. Knepley     array = *values;
6158e5c487bfSMatthew G. Knepley   }
61599566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6160e5c487bfSMatthew G. Knepley   /* Get values */
61619566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
61629566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6163e5c487bfSMatthew G. Knepley   /* Cleanup points */
61649566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6165e5c487bfSMatthew G. Knepley   /* Cleanup array */
61669566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6167e5c487bfSMatthew G. Knepley   if (!*values) {
6168e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6169e5c487bfSMatthew G. Knepley     *values = array;
6170e5c487bfSMatthew G. Knepley   } else {
617163a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6172e5c487bfSMatthew G. Knepley     *csize = size;
6173e5c487bfSMatthew G. Knepley   }
61743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6175e5c487bfSMatthew G. Knepley }
6176e5c487bfSMatthew G. Knepley 
6177552f7358SJed Brown /*@C
6178552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6179552f7358SJed Brown 
6180552f7358SJed Brown   Not collective
6181552f7358SJed Brown 
6182552f7358SJed Brown   Input Parameters:
6183a1cb98faSBarry Smith + dm - The `DM`
618420f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6185552f7358SJed Brown . v - The local vector
6186a1cb98faSBarry Smith . point - The point in the `DM`
618720f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL`
6188552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
6189552f7358SJed Brown 
6190552f7358SJed Brown   Level: intermediate
6191552f7358SJed Brown 
6192a1cb98faSBarry Smith   Note:
619320f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6194a1cb98faSBarry Smith 
6195a1cb98faSBarry Smith   Fortran Note:
619620f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6197a1cb98faSBarry Smith 
61981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6199552f7358SJed Brown @*/
6200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6201d71ae5a4SJacob Faibussowitsch {
6202552f7358SJed Brown   PetscInt size = 0;
6203552f7358SJed Brown 
6204552f7358SJed Brown   PetscFunctionBegin;
6205552f7358SJed Brown   /* Should work without recalculating size */
62069566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6207c9fdaa05SMatthew G. Knepley   *values = NULL;
62083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6209552f7358SJed Brown }
6210552f7358SJed Brown 
6211d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6212d71ae5a4SJacob Faibussowitsch {
62139371c9d4SSatish Balay   *x += y;
62149371c9d4SSatish Balay }
6215d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6216d71ae5a4SJacob Faibussowitsch {
62179371c9d4SSatish Balay   *x = y;
62189371c9d4SSatish Balay }
6219552f7358SJed Brown 
6220d71ae5a4SJacob 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[])
6221d71ae5a4SJacob Faibussowitsch {
6222552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6223552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6224552f7358SJed Brown   PetscScalar    *a;
6225552f7358SJed Brown   PetscInt        off, cind = 0, k;
6226552f7358SJed Brown 
6227552f7358SJed Brown   PetscFunctionBegin;
62289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
62299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6230552f7358SJed Brown   a = &array[off];
6231552f7358SJed Brown   if (!cdof || setBC) {
623297e99dd9SToby Isaac     if (clperm) {
62339371c9d4SSatish Balay       if (perm) {
6234ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6235552f7358SJed Brown       } else {
6236ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
62379371c9d4SSatish Balay       }
62389371c9d4SSatish Balay     } else {
62399371c9d4SSatish Balay       if (perm) {
6240ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
62419371c9d4SSatish Balay       } else {
6242ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
62439371c9d4SSatish Balay       }
6244552f7358SJed Brown     }
6245552f7358SJed Brown   } else {
62469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
624797e99dd9SToby Isaac     if (clperm) {
62489371c9d4SSatish Balay       if (perm) {
62499371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
62509371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62519371c9d4SSatish Balay             ++cind;
62529371c9d4SSatish Balay             continue;
62539371c9d4SSatish Balay           }
625497e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6255552f7358SJed Brown         }
6256552f7358SJed Brown       } else {
6257552f7358SJed Brown         for (k = 0; k < dof; ++k) {
62589371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62599371c9d4SSatish Balay             ++cind;
62609371c9d4SSatish Balay             continue;
62619371c9d4SSatish Balay           }
626297e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
626397e99dd9SToby Isaac         }
626497e99dd9SToby Isaac       }
626597e99dd9SToby Isaac     } else {
626697e99dd9SToby Isaac       if (perm) {
626797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
62689371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62699371c9d4SSatish Balay             ++cind;
62709371c9d4SSatish Balay             continue;
62719371c9d4SSatish Balay           }
627297e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
627397e99dd9SToby Isaac         }
627497e99dd9SToby Isaac       } else {
627597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
62769371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62779371c9d4SSatish Balay             ++cind;
62789371c9d4SSatish Balay             continue;
62799371c9d4SSatish Balay           }
628097e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
628197e99dd9SToby Isaac         }
6282552f7358SJed Brown       }
6283552f7358SJed Brown     }
6284552f7358SJed Brown   }
62853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6286552f7358SJed Brown }
6287552f7358SJed Brown 
6288d71ae5a4SJacob 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[])
6289d71ae5a4SJacob Faibussowitsch {
6290a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6291a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6292a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6293a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6294a5e93ea8SMatthew G. Knepley 
6295a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
62969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
62979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6298a5e93ea8SMatthew G. Knepley   a = &array[off];
6299a5e93ea8SMatthew G. Knepley   if (cdof) {
63009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
630197e99dd9SToby Isaac     if (clperm) {
630297e99dd9SToby Isaac       if (perm) {
6303a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6304a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
630597e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
630697e99dd9SToby Isaac             cind++;
6307a5e93ea8SMatthew G. Knepley           }
6308a5e93ea8SMatthew G. Knepley         }
6309a5e93ea8SMatthew G. Knepley       } else {
6310a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6311a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
631297e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
631397e99dd9SToby Isaac             cind++;
631497e99dd9SToby Isaac           }
631597e99dd9SToby Isaac         }
631697e99dd9SToby Isaac       }
631797e99dd9SToby Isaac     } else {
631897e99dd9SToby Isaac       if (perm) {
631997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
632097e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
632197e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
632297e99dd9SToby Isaac             cind++;
632397e99dd9SToby Isaac           }
632497e99dd9SToby Isaac         }
632597e99dd9SToby Isaac       } else {
632697e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
632797e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
632897e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
632997e99dd9SToby Isaac             cind++;
633097e99dd9SToby Isaac           }
6331a5e93ea8SMatthew G. Knepley         }
6332a5e93ea8SMatthew G. Knepley       }
6333a5e93ea8SMatthew G. Knepley     }
6334a5e93ea8SMatthew G. Knepley   }
63353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6336a5e93ea8SMatthew G. Knepley }
6337a5e93ea8SMatthew G. Knepley 
6338d71ae5a4SJacob 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[])
6339d71ae5a4SJacob Faibussowitsch {
6340552f7358SJed Brown   PetscScalar    *a;
63411a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
63421a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
634397e99dd9SToby Isaac   PetscInt        cind = 0, b;
6344552f7358SJed Brown 
6345552f7358SJed Brown   PetscFunctionBegin;
63469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
63489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63491a271a75SMatthew G. Knepley   a = &array[foff];
6350552f7358SJed Brown   if (!fcdof || setBC) {
635197e99dd9SToby Isaac     if (clperm) {
63529371c9d4SSatish Balay       if (perm) {
6353ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6354552f7358SJed Brown       } else {
6355ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
63569371c9d4SSatish Balay       }
63579371c9d4SSatish Balay     } else {
63589371c9d4SSatish Balay       if (perm) {
6359ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
63609371c9d4SSatish Balay       } else {
6361ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
63629371c9d4SSatish Balay       }
6363552f7358SJed Brown     }
6364552f7358SJed Brown   } else {
63659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
636697e99dd9SToby Isaac     if (clperm) {
636797e99dd9SToby Isaac       if (perm) {
636897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63699371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63709371c9d4SSatish Balay             ++cind;
63719371c9d4SSatish Balay             continue;
63729371c9d4SSatish Balay           }
637397e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6374552f7358SJed Brown         }
6375552f7358SJed Brown       } else {
637697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63779371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63789371c9d4SSatish Balay             ++cind;
63799371c9d4SSatish Balay             continue;
63809371c9d4SSatish Balay           }
638197e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
638297e99dd9SToby Isaac         }
638397e99dd9SToby Isaac       }
638497e99dd9SToby Isaac     } else {
638597e99dd9SToby Isaac       if (perm) {
638697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63879371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63889371c9d4SSatish Balay             ++cind;
63899371c9d4SSatish Balay             continue;
63909371c9d4SSatish Balay           }
639197e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
639297e99dd9SToby Isaac         }
639397e99dd9SToby Isaac       } else {
639497e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63959371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63969371c9d4SSatish Balay             ++cind;
63979371c9d4SSatish Balay             continue;
63989371c9d4SSatish Balay           }
639997e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6400552f7358SJed Brown         }
6401552f7358SJed Brown       }
6402552f7358SJed Brown     }
6403552f7358SJed Brown   }
64041a271a75SMatthew G. Knepley   *offset += fdof;
64053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6406552f7358SJed Brown }
6407552f7358SJed Brown 
6408d71ae5a4SJacob 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[])
6409d71ae5a4SJacob Faibussowitsch {
6410a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
64111a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
64121a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
64135da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6414ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6415a5e93ea8SMatthew G. Knepley 
6416a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
64179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
64189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
64209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
64211a271a75SMatthew G. Knepley   a = &array[foff];
6422a5e93ea8SMatthew G. Knepley   if (fcdof) {
6423ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
64249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
642597e99dd9SToby Isaac     if (clperm) {
642697e99dd9SToby Isaac       if (perm) {
6427ba322698SMatthew G. Knepley         if (comps) {
6428ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6429ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64309371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64319371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64329371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64339371c9d4SSatish Balay             }
64349371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64359371c9d4SSatish Balay               ++cind;
64369371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64379371c9d4SSatish Balay             }
6438ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6439ba322698SMatthew G. Knepley           }
6440ba322698SMatthew G. Knepley         } else {
644197e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
644297e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
644397e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6444a5e93ea8SMatthew G. Knepley               ++cind;
6445a5e93ea8SMatthew G. Knepley             }
6446a5e93ea8SMatthew G. Knepley           }
6447ba322698SMatthew G. Knepley         }
6448ba322698SMatthew G. Knepley       } else {
6449ba322698SMatthew G. Knepley         if (comps) {
6450ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6451ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64529371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64539371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64549371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64559371c9d4SSatish Balay             }
64569371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64579371c9d4SSatish Balay               ++cind;
64589371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64599371c9d4SSatish Balay             }
6460ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6461ba322698SMatthew G. Knepley           }
6462a5e93ea8SMatthew G. Knepley         } else {
646397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
646497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
646597e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
646697e99dd9SToby Isaac               ++cind;
646797e99dd9SToby Isaac             }
646897e99dd9SToby Isaac           }
646997e99dd9SToby Isaac         }
6470ba322698SMatthew G. Knepley       }
647197e99dd9SToby Isaac     } else {
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[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[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
649097e99dd9SToby Isaac               ++cind;
649197e99dd9SToby Isaac             }
649297e99dd9SToby Isaac           }
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[foffset + b] * (flip ? flip[b] : 1.));
6507ba322698SMatthew G. Knepley           }
650897e99dd9SToby Isaac         } else {
650997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
651097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
651197e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6512a5e93ea8SMatthew G. Knepley               ++cind;
6513a5e93ea8SMatthew G. Knepley             }
6514a5e93ea8SMatthew G. Knepley           }
6515a5e93ea8SMatthew G. Knepley         }
6516a5e93ea8SMatthew G. Knepley       }
6517a5e93ea8SMatthew G. Knepley     }
6518ba322698SMatthew G. Knepley   }
65191a271a75SMatthew G. Knepley   *offset += fdof;
65203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6521a5e93ea8SMatthew G. Knepley }
6522a5e93ea8SMatthew G. Knepley 
6523d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6524d71ae5a4SJacob Faibussowitsch {
6525552f7358SJed Brown   PetscScalar    *array;
65261b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
65271b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6528552f7358SJed Brown 
65291b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
65309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
65319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
65329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
65339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
65349566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6535b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6536b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6537b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6538b6ebb6e6SMatthew G. Knepley 
65399371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
65409371c9d4SSatish Balay       dof = 0;
65419371c9d4SSatish Balay       continue;
65429371c9d4SSatish Balay     }
65439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6544b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6545b6ebb6e6SMatthew G. Knepley     {
6546b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6547b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6548b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6549b6ebb6e6SMatthew G. Knepley 
65509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
65519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6552b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6553b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6554b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6555ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6556b6ebb6e6SMatthew G. Knepley         } else {
6557ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6558b6ebb6e6SMatthew G. Knepley         }
6559b6ebb6e6SMatthew G. Knepley       } else {
65609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6561b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6562b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
65639371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
65649371c9d4SSatish Balay               ++cind;
65659371c9d4SSatish Balay               continue;
65669371c9d4SSatish Balay             }
6567b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6568b6ebb6e6SMatthew G. Knepley           }
6569b6ebb6e6SMatthew G. Knepley         } else {
6570b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
65719371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
65729371c9d4SSatish Balay               ++cind;
65739371c9d4SSatish Balay               continue;
65749371c9d4SSatish Balay             }
6575b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6576b6ebb6e6SMatthew G. Knepley           }
6577b6ebb6e6SMatthew G. Knepley         }
6578b6ebb6e6SMatthew G. Knepley       }
6579b6ebb6e6SMatthew G. Knepley     }
6580b6ebb6e6SMatthew G. Knepley   }
65819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
65823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6583b6ebb6e6SMatthew G. Knepley }
65841b406b76SMatthew G. Knepley 
65851b406b76SMatthew G. Knepley /*@C
658620f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
65871b406b76SMatthew G. Knepley 
65881b406b76SMatthew G. Knepley   Not collective
65891b406b76SMatthew G. Knepley 
65901b406b76SMatthew G. Knepley   Input Parameters:
6591a1cb98faSBarry Smith + dm - The `DM`
659220f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
65931b406b76SMatthew G. Knepley . v - The local vector
659420f4b53cSBarry Smith . point - The point in the `DM`
65951b406b76SMatthew G. Knepley . values - The array of values
6596a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6597a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
65981b406b76SMatthew G. Knepley 
65991b406b76SMatthew G. Knepley   Level: intermediate
66001b406b76SMatthew G. Knepley 
66011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
66021b406b76SMatthew G. Knepley @*/
6603d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6604d71ae5a4SJacob Faibussowitsch {
66051b406b76SMatthew G. Knepley   PetscSection    clSection;
66061b406b76SMatthew G. Knepley   IS              clPoints;
66071b406b76SMatthew G. Knepley   PetscScalar    *array;
66081b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
660927f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6610c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
66111b406b76SMatthew G. Knepley 
66121a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
66131b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66149566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
66151a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
66161a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
66179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
66189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
66191b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
66209566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
66213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
66221b406b76SMatthew G. Knepley   }
66231a271a75SMatthew G. Knepley   /* Get points */
662407218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6625c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6626c459fbc1SJed Brown     PetscInt dof;
66279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6628c459fbc1SJed Brown     clsize += dof;
6629c459fbc1SJed Brown   }
66309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
66311a271a75SMatthew G. Knepley   /* Get array */
66329566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
66331a271a75SMatthew G. Knepley   /* Get values */
6634ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
663597e99dd9SToby Isaac     PetscInt offset = 0, f;
6636552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
663797e99dd9SToby Isaac       const PetscInt    **perms = NULL;
663897e99dd9SToby Isaac       const PetscScalar **flips = NULL;
663997e99dd9SToby Isaac 
66409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6641552f7358SJed Brown       switch (mode) {
6642552f7358SJed Brown       case INSERT_VALUES:
664397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
664497e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
664597e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
664697e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66473ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
66489371c9d4SSatish Balay         }
66499371c9d4SSatish Balay         break;
6650552f7358SJed Brown       case INSERT_ALL_VALUES:
665197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
665297e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
665397e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
665497e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66553ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
66569371c9d4SSatish Balay         }
66579371c9d4SSatish Balay         break;
6658a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
665997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
666097e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
666197e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
666297e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66633ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
66649371c9d4SSatish Balay         }
66659371c9d4SSatish Balay         break;
6666552f7358SJed Brown       case ADD_VALUES:
666797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
666897e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
666997e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
667097e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66713ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
66729371c9d4SSatish Balay         }
66739371c9d4SSatish Balay         break;
6674552f7358SJed Brown       case ADD_ALL_VALUES:
667597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
667697e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
667797e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
667897e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66793ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
66809371c9d4SSatish Balay         }
66819371c9d4SSatish Balay         break;
6682304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
668397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
668497e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
668597e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
668697e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66873ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
66889371c9d4SSatish Balay         }
66899371c9d4SSatish Balay         break;
6690d71ae5a4SJacob Faibussowitsch       default:
6691d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6692552f7358SJed Brown       }
66939566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
66941a271a75SMatthew G. Knepley     }
6695552f7358SJed Brown   } else {
66961a271a75SMatthew G. Knepley     PetscInt            dof, off;
669797e99dd9SToby Isaac     const PetscInt    **perms = NULL;
669897e99dd9SToby Isaac     const PetscScalar **flips = NULL;
66991a271a75SMatthew G. Knepley 
67009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
6701552f7358SJed Brown     switch (mode) {
6702552f7358SJed Brown     case INSERT_VALUES:
670397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
670497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
670597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
670697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67083ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
67099371c9d4SSatish Balay       }
67109371c9d4SSatish Balay       break;
6711552f7358SJed Brown     case INSERT_ALL_VALUES:
671297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
671397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
671497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
671597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67173ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
67189371c9d4SSatish Balay       }
67199371c9d4SSatish Balay       break;
6720a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
672197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
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;
67259566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67263ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
67279371c9d4SSatish Balay       }
67289371c9d4SSatish Balay       break;
6729552f7358SJed Brown     case ADD_VALUES:
673097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
673197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
673297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
673397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67353ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
67369371c9d4SSatish Balay       }
67379371c9d4SSatish Balay       break;
6738552f7358SJed Brown     case ADD_ALL_VALUES:
673997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
674097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
674197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
674297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67439566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67443ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
67459371c9d4SSatish Balay       }
67469371c9d4SSatish Balay       break;
6747304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
674897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
674997e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
675097e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
675197e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67529566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67533ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
67549371c9d4SSatish Balay       }
67559371c9d4SSatish Balay       break;
6756d71ae5a4SJacob Faibussowitsch     default:
6757d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6758552f7358SJed Brown     }
67599566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
6760552f7358SJed Brown   }
67611a271a75SMatthew G. Knepley   /* Cleanup points */
67629566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
67631a271a75SMatthew G. Knepley   /* Cleanup array */
67649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
67653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6766552f7358SJed Brown }
6767552f7358SJed Brown 
6768cfb853baSMatthew G. Knepley PetscErrorCode DMPlexVecSetStar(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6769cfb853baSMatthew G. Knepley {
6770cfb853baSMatthew G. Knepley   const PetscInt *supp, *cone;
6771cfb853baSMatthew G. Knepley   PetscScalar    *a;
6772cfb853baSMatthew G. Knepley   PetscInt        dim, Ns, dof, off, n = 0;
6773cfb853baSMatthew G. Knepley 
6774cfb853baSMatthew G. Knepley   PetscFunctionBegin;
6775cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6776cfb853baSMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6777cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6778cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
6779cfb853baSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) {
6780cfb853baSMatthew G. Knepley     PetscInt vStart, vEnd;
6781cfb853baSMatthew G. Knepley 
6782cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
6783cfb853baSMatthew G. Knepley     PetscCheck(point >= vStart && point < vEnd, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " must be a vertex in [%" PetscInt_FMT ", %" PetscInt_FMT "]", point, vStart, vEnd);
6784cfb853baSMatthew G. Knepley   }
6785cfb853baSMatthew G. Knepley   PetscValidScalarPointer(values, 5);
6786cfb853baSMatthew G. Knepley 
6787cfb853baSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
6788cfb853baSMatthew G. Knepley   PetscCall(DMPlexGetSupportSize(dm, point, &Ns));
6789cfb853baSMatthew G. Knepley   PetscCall(DMPlexGetSupport(dm, point, &supp));
6790cfb853baSMatthew G. Knepley   PetscCheck(Ns == 2 * dim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " has support size %" PetscInt_FMT " != %" PetscInt_FMT, point, Ns, 2 * dim);
6791cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(v, &a));
6792cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetDof(section, point, &dof));
6793cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetOffset(section, point, &off));
6794cfb853baSMatthew G. Knepley   for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6795cfb853baSMatthew G. Knepley   for (PetscInt d = 0; d < dim; ++d) {
6796cfb853baSMatthew G. Knepley     // Left edge
6797cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetCone(dm, supp[2 * d + 0], &cone));
6798cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, cone[0], &dof));
6799cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(section, cone[0], &off));
6800cfb853baSMatthew G. Knepley     for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6801cfb853baSMatthew G. Knepley     // Right edge
6802cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetCone(dm, supp[2 * d + 1], &cone));
6803cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, cone[1], &dof));
6804cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(section, cone[1], &off));
6805cfb853baSMatthew G. Knepley     for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6806cfb853baSMatthew G. Knepley   }
6807cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(v, &a));
68083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6809cfb853baSMatthew G. Knepley }
6810cfb853baSMatthew G. Knepley 
68115f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
6812d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
6813d71ae5a4SJacob Faibussowitsch {
68145f790a90SMatthew G. Knepley   PetscFunctionBegin;
681511cc89d2SBarry Smith   *contains = PETSC_TRUE;
68165f790a90SMatthew G. Knepley   if (label) {
6817d6177c40SToby Isaac     PetscInt fdof;
68185f790a90SMatthew G. Knepley 
681911cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
682011cc89d2SBarry Smith     if (!*contains) {
68219566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
68225f790a90SMatthew G. Knepley       *offset += fdof;
68233ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
68245f790a90SMatthew G. Knepley     }
68255f790a90SMatthew G. Knepley   }
68263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68275f790a90SMatthew G. Knepley }
68285f790a90SMatthew G. Knepley 
682997529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
6830d71ae5a4SJacob 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)
6831d71ae5a4SJacob Faibussowitsch {
6832e07394fbSMatthew G. Knepley   PetscSection    clSection;
6833e07394fbSMatthew G. Knepley   IS              clPoints;
6834e07394fbSMatthew G. Knepley   PetscScalar    *array;
6835e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
683697529cf3SJed Brown   const PetscInt *clp;
6837e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
683897e99dd9SToby Isaac   PetscInt        offset = 0, f;
6839e07394fbSMatthew G. Knepley 
6840e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6841e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68429566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6843e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6844e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
68459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6846e07394fbSMatthew G. Knepley   /* Get points */
684707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6848e07394fbSMatthew G. Knepley   /* Get array */
68499566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6850e07394fbSMatthew G. Knepley   /* Get values */
6851e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
685297e99dd9SToby Isaac     const PetscInt    **perms = NULL;
685397e99dd9SToby Isaac     const PetscScalar **flips = NULL;
685411cc89d2SBarry Smith     PetscBool           contains;
685597e99dd9SToby Isaac 
6856e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6857e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
6858e07394fbSMatthew G. Knepley         PetscInt fdof;
68599566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6860e07394fbSMatthew G. Knepley         offset += fdof;
6861e07394fbSMatthew G. Knepley       }
6862e07394fbSMatthew G. Knepley       continue;
6863e07394fbSMatthew G. Knepley     }
68649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6865e07394fbSMatthew G. Knepley     switch (mode) {
6866e07394fbSMatthew G. Knepley     case INSERT_VALUES:
686797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
686897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
686997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
687097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
687111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
687211cc89d2SBarry Smith         if (!contains) continue;
68739566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
68749371c9d4SSatish Balay       }
68759371c9d4SSatish Balay       break;
6876e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
687797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
687897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
687997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
688097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
688111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
688211cc89d2SBarry Smith         if (!contains) continue;
68839566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
68849371c9d4SSatish Balay       }
68859371c9d4SSatish Balay       break;
6886e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
688797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
688897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
688997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
689097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
689111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
689211cc89d2SBarry Smith         if (!contains) continue;
68939566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
68949371c9d4SSatish Balay       }
68959371c9d4SSatish Balay       break;
6896e07394fbSMatthew G. Knepley     case ADD_VALUES:
689797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
689897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
689997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
690097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
690111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
690211cc89d2SBarry Smith         if (!contains) continue;
69039566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
69049371c9d4SSatish Balay       }
69059371c9d4SSatish Balay       break;
6906e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
690797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
690897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
690997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
691097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
691111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
691211cc89d2SBarry Smith         if (!contains) continue;
69139566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
69149371c9d4SSatish Balay       }
69159371c9d4SSatish Balay       break;
6916d71ae5a4SJacob Faibussowitsch     default:
6917d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6918e07394fbSMatthew G. Knepley     }
69199566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6920e07394fbSMatthew G. Knepley   }
6921e07394fbSMatthew G. Knepley   /* Cleanup points */
69229566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6923e07394fbSMatthew G. Knepley   /* Cleanup array */
69249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6926e07394fbSMatthew G. Knepley }
6927e07394fbSMatthew G. Knepley 
6928d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6929d71ae5a4SJacob Faibussowitsch {
6930552f7358SJed Brown   PetscMPIInt rank;
6931552f7358SJed Brown   PetscInt    i, j;
6932552f7358SJed Brown 
6933552f7358SJed Brown   PetscFunctionBegin;
69349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
693563a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
693663a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
693763a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6938b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
69393ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
6940b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
69419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6942b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6943519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
69449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
6945552f7358SJed Brown #else
69469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
6947552f7358SJed Brown #endif
6948552f7358SJed Brown     }
69499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6950552f7358SJed Brown   }
69513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6952552f7358SJed Brown }
6953552f7358SJed Brown 
695405586334SMatthew G. Knepley /*
695505586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
695605586334SMatthew G. Knepley 
695705586334SMatthew G. Knepley   Input Parameters:
695805586334SMatthew G. Knepley + section - The section for this data layout
695936fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
696005586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
696105586334SMatthew G. Knepley . off     - The global offset of this point
696205586334SMatthew G. Knepley . loff    - The local offset of each field
6963a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
696405586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
696505586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
696605586334SMatthew G. Knepley 
696705586334SMatthew G. Knepley   Output Parameter:
696805586334SMatthew G. Knepley . indices - Indices for dofs on this point
696905586334SMatthew G. Knepley 
697005586334SMatthew G. Knepley   Level: developer
697105586334SMatthew G. Knepley 
697205586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
697305586334SMatthew G. Knepley */
6974d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6975d71ae5a4SJacob Faibussowitsch {
6976e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6977552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6978552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6979552f7358SJed Brown   PetscInt        cind = 0, k;
6980552f7358SJed Brown 
6981552f7358SJed Brown   PetscFunctionBegin;
698208401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
69839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
69849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6985552f7358SJed Brown   if (!cdof || setBC) {
698605586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
698705586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
698805586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
698905586334SMatthew G. Knepley 
699005586334SMatthew G. Knepley       indices[ind] = off + k;
6991552f7358SJed Brown     }
6992552f7358SJed Brown   } else {
69939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
69944acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
699505586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
699605586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
699705586334SMatthew G. Knepley 
69984acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
69994acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
700005586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
70014acb8e1eSToby Isaac         ++cind;
70024acb8e1eSToby Isaac       } else {
700336fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7004552f7358SJed Brown       }
7005552f7358SJed Brown     }
7006552f7358SJed Brown   }
7007e6ccafaeSMatthew G Knepley   *loff += dof;
70083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7009552f7358SJed Brown }
7010552f7358SJed Brown 
70117e29afd2SMatthew G. Knepley /*
701236fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
70137e29afd2SMatthew G. Knepley 
701436fa2b79SJed Brown  Input Parameters:
701536fa2b79SJed Brown + section - a section (global or local)
701620f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
701736fa2b79SJed Brown . point - point within section
701836fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
701936fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
702036fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
702136fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
702236fa2b79SJed Brown . permsoff - offset
702336fa2b79SJed Brown - indperm - index permutation
702436fa2b79SJed Brown 
702536fa2b79SJed Brown  Output Parameter:
702636fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
702736fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
702836fa2b79SJed Brown 
702936fa2b79SJed Brown  Notes:
703036fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
703136fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
703236fa2b79SJed Brown  in the local vector.
703336fa2b79SJed Brown 
703436fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
703536fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
703636fa2b79SJed Brown 
703736fa2b79SJed Brown  Developer Note:
703836fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
703936fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
704036fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
704136fa2b79SJed Brown 
704236fa2b79SJed Brown  Example:
704336fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
704436fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
704536fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
704636fa2b79SJed 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.
704736fa2b79SJed Brown 
704836fa2b79SJed Brown  Level: developer
70497e29afd2SMatthew G. Knepley */
7050d71ae5a4SJacob 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[])
7051d71ae5a4SJacob Faibussowitsch {
7052552f7358SJed Brown   PetscInt numFields, foff, f;
7053552f7358SJed Brown 
7054552f7358SJed Brown   PetscFunctionBegin;
705508401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
70569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7057552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
70584acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7059552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
70604acb8e1eSToby Isaac     PetscInt        cind = 0, b;
70614acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7062552f7358SJed Brown 
70639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7065552f7358SJed Brown     if (!cfdof || setBC) {
706605586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
706705586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
706805586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
706905586334SMatthew G. Knepley 
707005586334SMatthew G. Knepley         indices[ind] = off + foff + b;
707105586334SMatthew G. Knepley       }
7072552f7358SJed Brown     } else {
70739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
707405586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
707505586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
707605586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
707705586334SMatthew G. Knepley 
70784acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
707905586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7080552f7358SJed Brown           ++cind;
7081552f7358SJed Brown         } else {
708236fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7083552f7358SJed Brown         }
7084552f7358SJed Brown       }
7085552f7358SJed Brown     }
708636fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7087552f7358SJed Brown     foffs[f] += fdof;
7088552f7358SJed Brown   }
70893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7090552f7358SJed Brown }
7091552f7358SJed Brown 
70927e29afd2SMatthew G. Knepley /*
70937e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
70947e29afd2SMatthew G. Knepley 
70957e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7096645102dcSJed Brown 
7097645102dcSJed Brown  Notes:
7098645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7099645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
71007e29afd2SMatthew G. Knepley */
7101d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7102d71ae5a4SJacob Faibussowitsch {
71037e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
71047e29afd2SMatthew G. Knepley 
71057e29afd2SMatthew G. Knepley   PetscFunctionBegin;
71069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
71077e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
71087e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
71097e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
71107e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
71117e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
71127e29afd2SMatthew G. Knepley 
71139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
71149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
71159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7116645102dcSJed Brown     if (!cfdof) {
711705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
711805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
711905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
712005586334SMatthew G. Knepley 
712105586334SMatthew G. Knepley         indices[ind] = foff + b;
712205586334SMatthew G. Knepley       }
71237e29afd2SMatthew G. Knepley     } else {
71249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
712505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
712605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
712705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
712805586334SMatthew G. Knepley 
71297e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
713005586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
71317e29afd2SMatthew G. Knepley           ++cind;
71327e29afd2SMatthew G. Knepley         } else {
713305586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
71347e29afd2SMatthew G. Knepley         }
71357e29afd2SMatthew G. Knepley       }
71367e29afd2SMatthew G. Knepley     }
71377e29afd2SMatthew G. Knepley     foffs[f] += fdof;
71387e29afd2SMatthew G. Knepley   }
71393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71407e29afd2SMatthew G. Knepley }
71417e29afd2SMatthew G. Knepley 
7142d71ae5a4SJacob 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)
7143d71ae5a4SJacob Faibussowitsch {
7144d3d1a6afSToby Isaac   Mat             cMat;
7145d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7146d3d1a6afSToby Isaac   IS              aIS;
7147d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7148d3d1a6afSToby Isaac   const PetscInt *anchors;
7149e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7150d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7151d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7152d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7153d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7154d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7155d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7156d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
71576ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7158d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7159d3d1a6afSToby Isaac 
7160d3d1a6afSToby Isaac   PetscFunctionBegin;
7161d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7162d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
71639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7164d3d1a6afSToby Isaac 
71659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7166d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7167d3d1a6afSToby Isaac   if (aSec) {
71689566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
71699566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
71709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7171d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7172d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7173d3d1a6afSToby Isaac      * into the global matrix anyway) */
7174d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7175d3d1a6afSToby Isaac       PetscInt b    = points[p];
71764b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7177d3d1a6afSToby Isaac 
71789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7179ad540459SPierre Jolivet       if (!bSecDof) continue;
718048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7181d3d1a6afSToby Isaac       if (bDof) {
7182d3d1a6afSToby Isaac         /* this point is constrained */
7183d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7184d3d1a6afSToby Isaac         PetscInt bOff, q;
7185d3d1a6afSToby Isaac 
7186d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7187d3d1a6afSToby Isaac         newNumPoints += bDof;
71889566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7189d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7190d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7191d3d1a6afSToby Isaac           PetscInt aDof;
7192d3d1a6afSToby Isaac 
71939566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7194d3d1a6afSToby Isaac           newNumIndices += aDof;
7195d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7196d3d1a6afSToby Isaac             PetscInt fDof;
7197d3d1a6afSToby Isaac 
71989566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7199d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7200d3d1a6afSToby Isaac           }
7201d3d1a6afSToby Isaac         }
72029371c9d4SSatish Balay       } else {
7203d3d1a6afSToby Isaac         /* this point is not constrained */
7204d3d1a6afSToby Isaac         newNumPoints++;
72054b2f2278SToby Isaac         newNumIndices += bSecDof;
7206d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7207d3d1a6afSToby Isaac           PetscInt fDof;
7208d3d1a6afSToby Isaac 
72099566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7210d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7211d3d1a6afSToby Isaac         }
7212d3d1a6afSToby Isaac       }
7213d3d1a6afSToby Isaac     }
7214d3d1a6afSToby Isaac   }
7215d3d1a6afSToby Isaac   if (!anyConstrained) {
721672b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
721772b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
721872b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
721972b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
72209566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
72213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7222d3d1a6afSToby Isaac   }
7223d3d1a6afSToby Isaac 
72246ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
72256ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
72266ecaa68aSToby Isaac 
7227f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7228d3d1a6afSToby Isaac 
72296ecaa68aSToby Isaac   if (!outPoints && !outValues) {
72306ecaa68aSToby Isaac     if (offsets) {
7231ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
72326ecaa68aSToby Isaac     }
72339566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
72343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
72356ecaa68aSToby Isaac   }
72366ecaa68aSToby Isaac 
72371dca8a05SBarry 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);
7238d3d1a6afSToby Isaac 
72399566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7240d3d1a6afSToby Isaac 
7241d3d1a6afSToby Isaac   /* workspaces */
7242d3d1a6afSToby Isaac   if (numFields) {
7243d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72449566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
72459566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7246d3d1a6afSToby Isaac     }
72479371c9d4SSatish Balay   } else {
72489566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
72499566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7250d3d1a6afSToby Isaac   }
7251d3d1a6afSToby Isaac 
7252d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7253d3d1a6afSToby Isaac   if (numFields) {
72544b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
72554b2f2278SToby Isaac 
7256d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7257d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
72584b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7259d3d1a6afSToby Isaac 
72609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
72614b2f2278SToby Isaac       if (!bSecDof) {
72624b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
72634b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
72644b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
72654b2f2278SToby Isaac         }
72664b2f2278SToby Isaac         continue;
72674b2f2278SToby Isaac       }
726848a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7269d3d1a6afSToby Isaac       if (bDof) {
7270d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7271d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7272d3d1a6afSToby Isaac 
72739566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
72749566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7275d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7276d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7277d3d1a6afSToby Isaac             PetscInt aFDof;
7278d3d1a6afSToby Isaac 
72799566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7280d3d1a6afSToby Isaac             allFDof += aFDof;
7281d3d1a6afSToby Isaac           }
7282d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7283d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7284d3d1a6afSToby Isaac         }
72859371c9d4SSatish Balay       } else {
7286d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7287d3d1a6afSToby Isaac           PetscInt fDof;
7288d3d1a6afSToby Isaac 
72899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7290d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7291d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7292d3d1a6afSToby Isaac         }
7293d3d1a6afSToby Isaac       }
7294d3d1a6afSToby Isaac     }
72954b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
72964b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
72974b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7298d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7299d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7300d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7301d3d1a6afSToby Isaac       }
730219f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
730319f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
73049566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7305d3d1a6afSToby Isaac     }
73069371c9d4SSatish Balay   } else {
7307d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7308d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
73094b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7310d3d1a6afSToby Isaac 
73119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
73124b2f2278SToby Isaac       if (!bSecDof) {
73134b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
73144b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
73154b2f2278SToby Isaac         continue;
73164b2f2278SToby Isaac       }
731748a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7318d3d1a6afSToby Isaac       if (bDof) {
73194b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7320d3d1a6afSToby Isaac 
73219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7322d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7323d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7324d3d1a6afSToby Isaac 
73259566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7326d3d1a6afSToby Isaac           allDof += aDof;
7327d3d1a6afSToby Isaac         }
7328d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
73294b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
73309371c9d4SSatish Balay       } else {
73314b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7332d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7333d3d1a6afSToby Isaac       }
7334d3d1a6afSToby Isaac     }
7335d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7336d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7337d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7338d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7339d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7340d3d1a6afSToby Isaac     }
73419566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7342d3d1a6afSToby Isaac   }
7343d3d1a6afSToby Isaac 
73446ecaa68aSToby Isaac   /* output arrays */
73459566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
73466ecaa68aSToby Isaac 
7347d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
73489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
73499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
73509566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
73519566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7352d3d1a6afSToby Isaac   if (numFields) {
7353d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7354d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7355d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
73564b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7357d3d1a6afSToby Isaac 
73589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7359ad540459SPierre Jolivet       if (!bSecDof) continue;
736048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7361d3d1a6afSToby Isaac       if (bDof) {
7362d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7363d3d1a6afSToby Isaac 
7364d3d1a6afSToby Isaac         fStart[0] = 0;
7365d3d1a6afSToby Isaac         fEnd[0]   = 0;
7366d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7367d3d1a6afSToby Isaac           PetscInt fDof;
7368d3d1a6afSToby Isaac 
73699566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7370d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7371d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7372d3d1a6afSToby Isaac         }
73739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
73749566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7375d3d1a6afSToby Isaac 
7376d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7377d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7378d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7379d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7380d3d1a6afSToby Isaac 
7381d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7382d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7383d3d1a6afSToby Isaac         }
73849566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7385d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7386d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7387d3d1a6afSToby Isaac 
7388d3d1a6afSToby 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 */
7389d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7390d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
73919566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
73929566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7393d3d1a6afSToby Isaac         }
7394d3d1a6afSToby Isaac         newP += bDof;
7395d3d1a6afSToby Isaac 
73966ecaa68aSToby Isaac         if (outValues) {
7397d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
739848a46eb9SPierre 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]));
7399d3d1a6afSToby Isaac         }
74009371c9d4SSatish Balay       } else {
7401d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7402d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7403d3d1a6afSToby Isaac         newP++;
7404d3d1a6afSToby Isaac       }
7405d3d1a6afSToby Isaac     }
7406d3d1a6afSToby Isaac   } else {
7407d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7408d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7409d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
74104b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7411d3d1a6afSToby Isaac 
74129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7413ad540459SPierre Jolivet       if (!bSecDof) continue;
741448a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7415d3d1a6afSToby Isaac       if (bDof) {
7416d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7417d3d1a6afSToby Isaac 
74189566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
74199566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7420d3d1a6afSToby Isaac 
74219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7422d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7423d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7424d3d1a6afSToby Isaac 
7425d3d1a6afSToby 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 */
7426d3d1a6afSToby Isaac 
7427d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7428d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
74299566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
74309566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7431d3d1a6afSToby Isaac         }
7432d3d1a6afSToby Isaac         newP += bDof;
7433d3d1a6afSToby Isaac 
7434d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
743548a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
74369371c9d4SSatish Balay       } else {
7437d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7438d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7439d3d1a6afSToby Isaac         newP++;
7440d3d1a6afSToby Isaac       }
7441d3d1a6afSToby Isaac     }
7442d3d1a6afSToby Isaac   }
7443d3d1a6afSToby Isaac 
74446ecaa68aSToby Isaac   if (outValues) {
74459566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
74469566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7447d3d1a6afSToby Isaac     /* multiply constraints on the right */
7448d3d1a6afSToby Isaac     if (numFields) {
7449d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7450d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7451d3d1a6afSToby Isaac 
7452d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7453d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7454d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7455d3d1a6afSToby Isaac           PetscInt c, r, k;
7456d3d1a6afSToby Isaac           PetscInt dof;
7457d3d1a6afSToby Isaac 
74589566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7459ad540459SPierre Jolivet           if (!dof) continue;
7460d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7461d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7462d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7463d3d1a6afSToby Isaac 
7464d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7465d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7466ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7467d3d1a6afSToby Isaac               }
7468d3d1a6afSToby Isaac             }
74699371c9d4SSatish Balay           } else {
7470d3d1a6afSToby Isaac             /* copy this column as is */
7471d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7472ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7473d3d1a6afSToby Isaac             }
7474d3d1a6afSToby Isaac           }
7475d3d1a6afSToby Isaac           oldOff += dof;
7476d3d1a6afSToby Isaac         }
7477d3d1a6afSToby Isaac       }
74789371c9d4SSatish Balay     } else {
7479d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7480d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7481d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7482d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7483d3d1a6afSToby Isaac         PetscInt c, r, k;
7484d3d1a6afSToby Isaac         PetscInt dof;
7485d3d1a6afSToby Isaac 
74869566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7487ad540459SPierre Jolivet         if (!dof) continue;
7488d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7489d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7490d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7491d3d1a6afSToby Isaac 
7492d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7493d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7494ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7495d3d1a6afSToby Isaac             }
7496d3d1a6afSToby Isaac           }
74979371c9d4SSatish Balay         } else {
7498d3d1a6afSToby Isaac           /* copy this column as is */
7499d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7500ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7501d3d1a6afSToby Isaac           }
7502d3d1a6afSToby Isaac         }
7503d3d1a6afSToby Isaac         oldOff += dof;
7504d3d1a6afSToby Isaac       }
7505d3d1a6afSToby Isaac     }
7506d3d1a6afSToby Isaac 
75076ecaa68aSToby Isaac     if (multiplyLeft) {
75089566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
75099566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7510d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7511d3d1a6afSToby Isaac       if (numFields) {
7512d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7513d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7514d3d1a6afSToby Isaac 
7515d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7516d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7517d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7518d3d1a6afSToby Isaac             PetscInt c, r, k;
7519d3d1a6afSToby Isaac             PetscInt dof;
7520d3d1a6afSToby Isaac 
75219566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7522d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7523d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7524d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7525d3d1a6afSToby Isaac 
7526d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7527d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7528ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7529d3d1a6afSToby Isaac                 }
7530d3d1a6afSToby Isaac               }
75319371c9d4SSatish Balay             } else {
7532d3d1a6afSToby Isaac               /* copy this row as is */
7533d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7534ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7535d3d1a6afSToby Isaac               }
7536d3d1a6afSToby Isaac             }
7537d3d1a6afSToby Isaac             oldOff += dof;
7538d3d1a6afSToby Isaac           }
7539d3d1a6afSToby Isaac         }
75409371c9d4SSatish Balay       } else {
7541d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7542d3d1a6afSToby Isaac 
7543d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7544d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7545d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7546d3d1a6afSToby Isaac           PetscInt c, r, k;
7547d3d1a6afSToby Isaac           PetscInt dof;
7548d3d1a6afSToby Isaac 
75499566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7550d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7551d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7552d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7553d3d1a6afSToby Isaac 
7554d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7555d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7556ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7557d3d1a6afSToby Isaac               }
7558d3d1a6afSToby Isaac             }
75599371c9d4SSatish Balay           } else {
7560d3d1a6afSToby Isaac             /* copy this row as is */
75619fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7562ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7563d3d1a6afSToby Isaac             }
7564d3d1a6afSToby Isaac           }
7565d3d1a6afSToby Isaac           oldOff += dof;
7566d3d1a6afSToby Isaac         }
7567d3d1a6afSToby Isaac       }
7568d3d1a6afSToby Isaac 
75699566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
75709371c9d4SSatish Balay     } else {
75716ecaa68aSToby Isaac       newValues = tmpValues;
75726ecaa68aSToby Isaac     }
75736ecaa68aSToby Isaac   }
75746ecaa68aSToby Isaac 
7575d3d1a6afSToby Isaac   /* clean up */
75769566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
75779566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
75786ecaa68aSToby Isaac 
7579d3d1a6afSToby Isaac   if (numFields) {
7580d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
75819566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
75829566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
75839566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7584d3d1a6afSToby Isaac     }
75859371c9d4SSatish Balay   } else {
75869566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
75879566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
75889566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7589d3d1a6afSToby Isaac   }
75909566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7591d3d1a6afSToby Isaac 
7592d3d1a6afSToby Isaac   /* output */
75936ecaa68aSToby Isaac   if (outPoints) {
7594d3d1a6afSToby Isaac     *outPoints = newPoints;
75959371c9d4SSatish Balay   } else {
75969566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
75976ecaa68aSToby Isaac   }
7598ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7599ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
76003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7601d3d1a6afSToby Isaac }
7602d3d1a6afSToby Isaac 
76034a1e0b3eSMatthew G. Knepley /*@C
760471f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
76057cd05799SMatthew G. Knepley 
76067cd05799SMatthew G. Knepley   Not collective
76077cd05799SMatthew G. Knepley 
76087cd05799SMatthew G. Knepley   Input Parameters:
7609a1cb98faSBarry Smith + dm         - The `DM`
7610a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7611a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
761271f0bbf9SMatthew G. Knepley . point      - The point defining the closure
761371f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
76147cd05799SMatthew G. Knepley 
761571f0bbf9SMatthew G. Knepley   Output Parameters:
761671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
761771f0bbf9SMatthew G. Knepley . indices    - The dof indices
761820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
761920f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
76207cd05799SMatthew G. Knepley 
7621a1cb98faSBarry Smith   Level: advanced
762236fa2b79SJed Brown 
7623a1cb98faSBarry Smith   Notes:
7624a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7625a1cb98faSBarry Smith 
762620f4b53cSBarry Smith   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
762720f4b53cSBarry Smith   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
762836fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
762920f4b53cSBarry Smith   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
763036fa2b79SJed Brown   indices (with the above semantics) are implied.
76317cd05799SMatthew G. Knepley 
76321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7633a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
76344a1e0b3eSMatthew G. Knepley @*/
7635d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7636d71ae5a4SJacob Faibussowitsch {
763771f0bbf9SMatthew G. Knepley   /* Closure ordering */
76387773e69fSMatthew G. Knepley   PetscSection    clSection;
76397773e69fSMatthew G. Knepley   IS              clPoints;
764071f0bbf9SMatthew G. Knepley   const PetscInt *clp;
764171f0bbf9SMatthew G. Knepley   PetscInt       *points;
764271f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
764371f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
76444acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
764571f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
764671f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
764771f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
764871f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
764971f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
765071f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
765171f0bbf9SMatthew G. Knepley 
765271f0bbf9SMatthew G. Knepley   PetscInt *idx;
765371f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
765471f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
76557773e69fSMatthew G. Knepley 
765671f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
76577773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
76587773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
765936fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7660dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
766171f0bbf9SMatthew G. Knepley   if (indices) PetscValidPointer(indices, 7);
7662dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
766371f0bbf9SMatthew G. Knepley   if (values) PetscValidPointer(values, 9);
76649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
766563a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
76669566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
766771f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
766807218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7669c459fbc1SJed Brown   if (useClPerm) {
7670c459fbc1SJed Brown     PetscInt depth, clsize;
76719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7672c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7673c459fbc1SJed Brown       PetscInt dof;
76749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7675c459fbc1SJed Brown       clsize += dof;
7676c459fbc1SJed Brown     }
76779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7678c459fbc1SJed Brown   }
767971f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
768071f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
76817773e69fSMatthew G. Knepley     PetscInt dof, fdof;
76827773e69fSMatthew G. Knepley 
76839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
76847773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
76859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
76867773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
76877773e69fSMatthew G. Knepley     }
768871f0bbf9SMatthew G. Knepley     Ni += dof;
76897773e69fSMatthew G. Knepley   }
76907773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
76911dca8a05SBarry 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);
769271f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
769371f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
76949566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
76959566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
769671f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
769771f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
769871f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
76996ecaa68aSToby Isaac 
770071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
770171f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
770271f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
770371f0bbf9SMatthew G. Knepley 
77049566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
77059566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
770671f0bbf9SMatthew G. Knepley         if (flip) {
770771f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
770871f0bbf9SMatthew G. Knepley 
770971f0bbf9SMatthew G. Knepley           if (!valCopy) {
77109566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
771171f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
771271f0bbf9SMatthew G. Knepley             *values = valCopy;
771371f0bbf9SMatthew G. Knepley           }
771471f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
771571f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
771671f0bbf9SMatthew G. Knepley 
771771f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
771871f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
771971f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
77206ecaa68aSToby Isaac             }
77216ecaa68aSToby Isaac           }
772271f0bbf9SMatthew G. Knepley         }
772371f0bbf9SMatthew G. Knepley         foffset += fdof;
772471f0bbf9SMatthew G. Knepley       }
772571f0bbf9SMatthew G. Knepley     }
772671f0bbf9SMatthew G. Knepley   }
772771f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
77289566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
772971f0bbf9SMatthew G. Knepley   if (NclC) {
77309566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
773171f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
77329566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
77339566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
773471f0bbf9SMatthew G. Knepley     }
773571f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
77369566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
77379566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
773871f0bbf9SMatthew G. Knepley     }
77399566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
774071f0bbf9SMatthew G. Knepley     Ncl    = NclC;
774171f0bbf9SMatthew G. Knepley     Ni     = NiC;
774271f0bbf9SMatthew G. Knepley     points = pointsC;
774371f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
774471f0bbf9SMatthew G. Knepley   }
774571f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
77469566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
774771f0bbf9SMatthew G. Knepley   if (Nf) {
774871f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
774971f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
775071f0bbf9SMatthew G. Knepley 
77519371c9d4SSatish Balay     if (outOffsets) {
77529371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
77539371c9d4SSatish Balay     }
77549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
775571f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
775671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
775771f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
775871f0bbf9SMatthew G. Knepley 
77599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
77607773e69fSMatthew G. Knepley       }
77617773e69fSMatthew G. Knepley     } else {
776271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
776371f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
776471f0bbf9SMatthew G. Knepley 
77659566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
776671f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
776771f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
776871f0bbf9SMatthew G. Knepley          * global section. */
77699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
777071f0bbf9SMatthew G. Knepley       }
777171f0bbf9SMatthew G. Knepley     }
777271f0bbf9SMatthew G. Knepley   } else {
777371f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
777471f0bbf9SMatthew G. Knepley 
777571f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
777671f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
77774acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
77784acb8e1eSToby Isaac 
77799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
778071f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
778171f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
77829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
77837773e69fSMatthew G. Knepley     }
77847773e69fSMatthew G. Knepley   }
778571f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
778671f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
77879566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
77889566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
77894acb8e1eSToby Isaac   }
779071f0bbf9SMatthew G. Knepley   if (NclC) {
77919566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
77927773e69fSMatthew G. Knepley   } else {
77939566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
77947773e69fSMatthew G. Knepley   }
779571f0bbf9SMatthew G. Knepley 
779671f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
779771f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
77983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77997773e69fSMatthew G. Knepley }
78007773e69fSMatthew G. Knepley 
78017cd05799SMatthew G. Knepley /*@C
780271f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
78037cd05799SMatthew G. Knepley 
78047cd05799SMatthew G. Knepley   Not collective
78057cd05799SMatthew G. Knepley 
78067cd05799SMatthew G. Knepley   Input Parameters:
7807a1cb98faSBarry Smith + dm         - The `DM`
7808a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7809a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
781071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
781171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
781271f0bbf9SMatthew G. Knepley 
781371f0bbf9SMatthew G. Knepley   Output Parameters:
781471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
781571f0bbf9SMatthew G. Knepley . indices    - The dof indices
781620f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
781720f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
781871f0bbf9SMatthew G. Knepley 
7819a1cb98faSBarry Smith   Level: advanced
782071f0bbf9SMatthew G. Knepley 
7821a1cb98faSBarry Smith   Notes:
7822a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
7823a1cb98faSBarry Smith 
7824a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
782571f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
782671f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
782771f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
782871f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
78297cd05799SMatthew G. Knepley 
78301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
78317cd05799SMatthew G. Knepley @*/
7832d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7833d71ae5a4SJacob Faibussowitsch {
78347773e69fSMatthew G. Knepley   PetscFunctionBegin;
78357773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7836064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
78379566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
78383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78397773e69fSMatthew G. Knepley }
78407773e69fSMatthew G. Knepley 
78417f5d1fdeSMatthew G. Knepley /*@C
78427f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
78437f5d1fdeSMatthew G. Knepley 
78447f5d1fdeSMatthew G. Knepley   Not collective
78457f5d1fdeSMatthew G. Knepley 
78467f5d1fdeSMatthew G. Knepley   Input Parameters:
7847a1cb98faSBarry Smith + dm - The `DM`
784820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
784920f4b53cSBarry Smith . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
78507f5d1fdeSMatthew G. Knepley . A - The matrix
7851a1cb98faSBarry Smith . point - The point in the `DM`
78527f5d1fdeSMatthew G. Knepley . values - The array of values
7853a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
78547f5d1fdeSMatthew G. Knepley 
78557f5d1fdeSMatthew G. Knepley   Level: intermediate
78567f5d1fdeSMatthew G. Knepley 
78571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
78587f5d1fdeSMatthew G. Knepley @*/
7859d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7860d71ae5a4SJacob Faibussowitsch {
7861552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
7862552f7358SJed Brown   PetscInt          *indices;
786371f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
786471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7865552f7358SJed Brown   PetscErrorCode     ierr;
7866552f7358SJed Brown 
7867552f7358SJed Brown   PetscFunctionBegin;
7868552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78699566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
78703dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
78719566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
78723dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
78733dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7874552f7358SJed Brown 
78759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78760d644c17SKarl Rupp 
78779566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7878d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
78794a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7880552f7358SJed Brown   if (ierr) {
7881552f7358SJed Brown     PetscMPIInt rank;
7882552f7358SJed Brown 
78839566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
78849566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
78859566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
78869566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78879566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7888c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
7889552f7358SJed Brown   }
78904a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
78914a1e0b3eSMatthew G. Knepley     PetscInt i;
78929566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
789363a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
78949566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
78954a1e0b3eSMatthew G. Knepley   }
789671f0bbf9SMatthew G. Knepley 
78979566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78989566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
78993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79004acb8e1eSToby Isaac }
790171f0bbf9SMatthew G. Knepley 
79024a1e0b3eSMatthew G. Knepley /*@C
79034a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
79044a1e0b3eSMatthew G. Knepley 
79054a1e0b3eSMatthew G. Knepley   Not collective
79064a1e0b3eSMatthew G. Knepley 
79074a1e0b3eSMatthew G. Knepley   Input Parameters:
7908a1cb98faSBarry Smith + dmRow - The `DM` for the row fields
790920f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow`
791020f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
7911a1cb98faSBarry Smith . dmCol - The `DM` for the column fields
791220f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol`
791320f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
79144a1e0b3eSMatthew G. Knepley . A - The matrix
7915a1cb98faSBarry Smith . point - The point in the `DM`
79164a1e0b3eSMatthew G. Knepley . values - The array of values
7917a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
79184a1e0b3eSMatthew G. Knepley 
79194a1e0b3eSMatthew G. Knepley   Level: intermediate
79204a1e0b3eSMatthew G. Knepley 
79211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
79224a1e0b3eSMatthew G. Knepley @*/
7923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7924d71ae5a4SJacob Faibussowitsch {
792571f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
792671f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
792771f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
792871f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
792971f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
793071f0bbf9SMatthew G. Knepley 
793171f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
793271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
79339566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
793471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
79359566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
793671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
793771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
79389566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
793971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
79409566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
794171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
794271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
794371f0bbf9SMatthew G. Knepley 
79449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
794671f0bbf9SMatthew G. Knepley 
79479566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7948d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
79494a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
795071f0bbf9SMatthew G. Knepley   if (ierr) {
795171f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
795271f0bbf9SMatthew G. Knepley 
79539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
79549566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
79559566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
79569566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79579566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
79589566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7959d3d1a6afSToby Isaac   }
796071f0bbf9SMatthew G. Knepley 
79619566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79629566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
79639566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
79643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7965552f7358SJed Brown }
7966552f7358SJed Brown 
7967d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7968d71ae5a4SJacob Faibussowitsch {
7969de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
7970de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7971de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7972de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
797317c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7974de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7975412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
79764ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7977de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7978de41b84cSMatthew G. Knepley 
7979de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7980de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7981de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
79829566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7983de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
79849566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7985de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
79869566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7987de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
79889566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7989de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7990de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
79919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
799263a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
79939566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
79949566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7995de41b84cSMatthew G. Knepley   /* Column indices */
79969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79974ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7998de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7999de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
80009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8001de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8002de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8003de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8004de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8005de41b84cSMatthew G. Knepley       ++q;
8006de41b84cSMatthew G. Knepley     }
8007de41b84cSMatthew G. Knepley   }
8008de41b84cSMatthew G. Knepley   numCPoints = q;
8009de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8010de41b84cSMatthew G. Knepley     PetscInt fdof;
8011de41b84cSMatthew G. Knepley 
80129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
80134ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8014de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
80159566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8016de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8017de41b84cSMatthew G. Knepley     }
8018de41b84cSMatthew G. Knepley     numCIndices += dof;
8019de41b84cSMatthew G. Knepley   }
8020de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8021de41b84cSMatthew G. Knepley   /* Row indices */
80229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8023412e9a14SMatthew G. Knepley   {
8024012bc364SMatthew G. Knepley     DMPlexTransform tr;
8025012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8026012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8027012bc364SMatthew G. Knepley 
80289566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
80299566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
80309566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8031012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
80329566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8033412e9a14SMatthew G. Knepley   }
80349566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8035de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8036de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
80379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8038de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
80399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8040de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8041de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
80429566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
80434ca5e9f5SMatthew G. Knepley         if (!dof) continue;
80449371c9d4SSatish Balay         for (s = 0; s < q; ++s)
80459371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
80464ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8047de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8048de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8049de41b84cSMatthew G. Knepley         ++q;
8050de41b84cSMatthew G. Knepley       }
8051de41b84cSMatthew G. Knepley     }
80529566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8053de41b84cSMatthew G. Knepley   }
8054de41b84cSMatthew G. Knepley   numFPoints = q;
8055de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8056de41b84cSMatthew G. Knepley     PetscInt fdof;
8057de41b84cSMatthew G. Knepley 
80589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
80594ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8060de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
80619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8062de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8063de41b84cSMatthew G. Knepley     }
8064de41b84cSMatthew G. Knepley     numFIndices += dof;
8065de41b84cSMatthew G. Knepley   }
8066de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8067de41b84cSMatthew G. Knepley 
80681dca8a05SBarry 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);
80691dca8a05SBarry 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);
80709566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80719566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8072de41b84cSMatthew G. Knepley   if (numFields) {
80734acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
80744acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
80754acb8e1eSToby Isaac 
80764acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8079de41b84cSMatthew G. Knepley     }
80804acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
80819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
80829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
80834acb8e1eSToby Isaac     }
80844acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
80859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
80869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
80874acb8e1eSToby Isaac     }
80884acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80899566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80909566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8091de41b84cSMatthew G. Knepley     }
8092de41b84cSMatthew G. Knepley   } else {
80934acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
80944acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
80954acb8e1eSToby Isaac 
80969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
80979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
80984acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
80994acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
81004acb8e1eSToby Isaac 
81019566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
81029566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8103de41b84cSMatthew G. Knepley     }
81044acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
81054acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
81064acb8e1eSToby Isaac 
81079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
81089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8109de41b84cSMatthew G. Knepley     }
81109566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
81119566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8112de41b84cSMatthew G. Knepley   }
81139566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
81144acb8e1eSToby Isaac   /* TODO: flips */
8115d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8116de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8117de41b84cSMatthew G. Knepley   if (ierr) {
8118de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8119de41b84cSMatthew G. Knepley 
81209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81219566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81229566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
81239566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
81249566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8125de41b84cSMatthew G. Knepley   }
81269566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
81279566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81289566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
81299566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
81303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8131de41b84cSMatthew G. Knepley }
8132de41b84cSMatthew G. Knepley 
8133d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8134d71ae5a4SJacob Faibussowitsch {
81357c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
81367c927364SMatthew G. Knepley   PetscInt       *cpoints = NULL;
81377c927364SMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
813817c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8139412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
81407c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
81417c927364SMatthew G. Knepley 
81427c927364SMatthew G. Knepley   PetscFunctionBegin;
81437c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
81447c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
81459566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
81467c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
81479566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
81487c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
81499566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
81507c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
81519566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
81527c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
81539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
815463a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
81559566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
81569566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
81577c927364SMatthew G. Knepley   /* Column indices */
81589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81597c927364SMatthew G. Knepley   maxFPoints = numCPoints;
81607c927364SMatthew G. Knepley   /* Compress out points not in the section */
81617c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
81629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
81637c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
81647c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
81657c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
81667c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
81677c927364SMatthew G. Knepley       ++q;
81687c927364SMatthew G. Knepley     }
81697c927364SMatthew G. Knepley   }
81707c927364SMatthew G. Knepley   numCPoints = q;
81717c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
81727c927364SMatthew G. Knepley     PetscInt fdof;
81737c927364SMatthew G. Knepley 
81749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
81757c927364SMatthew G. Knepley     if (!dof) continue;
81767c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
81779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
81787c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
81797c927364SMatthew G. Knepley     }
81807c927364SMatthew G. Knepley     numCIndices += dof;
81817c927364SMatthew G. Knepley   }
81827c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
81837c927364SMatthew G. Knepley   /* Row indices */
81849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8185412e9a14SMatthew G. Knepley   {
8186012bc364SMatthew G. Knepley     DMPlexTransform tr;
8187012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8188012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8189012bc364SMatthew G. Knepley 
81909566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
81919566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
81929566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8193012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
81949566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8195412e9a14SMatthew G. Knepley   }
81969566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
81977c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
81987c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
81999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
82007c927364SMatthew G. Knepley     /* Compress out points not in the section */
82019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
82027c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
82037c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
82049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
82057c927364SMatthew G. Knepley         if (!dof) continue;
82069371c9d4SSatish Balay         for (s = 0; s < q; ++s)
82079371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
82087c927364SMatthew G. Knepley         if (s < q) continue;
82097c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
82107c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
82117c927364SMatthew G. Knepley         ++q;
82127c927364SMatthew G. Knepley       }
82137c927364SMatthew G. Knepley     }
82149566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
82157c927364SMatthew G. Knepley   }
82167c927364SMatthew G. Knepley   numFPoints = q;
82177c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
82187c927364SMatthew G. Knepley     PetscInt fdof;
82197c927364SMatthew G. Knepley 
82209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
82217c927364SMatthew G. Knepley     if (!dof) continue;
82227c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
82239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
82247c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
82257c927364SMatthew G. Knepley     }
82267c927364SMatthew G. Knepley     numFIndices += dof;
82277c927364SMatthew G. Knepley   }
82287c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
82297c927364SMatthew G. Knepley 
82301dca8a05SBarry 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);
82311dca8a05SBarry 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);
82327c927364SMatthew G. Knepley   if (numFields) {
82334acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
82344acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
82354acb8e1eSToby Isaac 
82364acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
82397c927364SMatthew G. Knepley     }
82404acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
82419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82429566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
82434acb8e1eSToby Isaac     }
82444acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
82459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
82474acb8e1eSToby Isaac     }
82484acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82499566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82509566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
82517c927364SMatthew G. Knepley     }
82527c927364SMatthew G. Knepley   } else {
82534acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
82544acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
82554acb8e1eSToby Isaac 
82569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82584acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
82594acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
82604acb8e1eSToby Isaac 
82619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
82637c927364SMatthew G. Knepley     }
82644acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
82654acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
82664acb8e1eSToby Isaac 
82679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
82697c927364SMatthew G. Knepley     }
82709566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82719566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82727c927364SMatthew G. Knepley   }
82739566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
82749566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
82753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82767c927364SMatthew G. Knepley }
82777c927364SMatthew G. Knepley 
82787cd05799SMatthew G. Knepley /*@C
82797cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
82807cd05799SMatthew G. Knepley 
82817cd05799SMatthew G. Knepley   Input Parameter:
8282a1cb98faSBarry Smith . dm   - The `DMPLEX` object
82837cd05799SMatthew G. Knepley 
82847cd05799SMatthew G. Knepley   Output Parameter:
82857cd05799SMatthew G. Knepley . cellHeight - The height of a cell
82867cd05799SMatthew G. Knepley 
82877cd05799SMatthew G. Knepley   Level: developer
82887cd05799SMatthew G. Knepley 
82891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
82907cd05799SMatthew G. Knepley @*/
8291d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8292d71ae5a4SJacob Faibussowitsch {
8293552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8294552f7358SJed Brown 
8295552f7358SJed Brown   PetscFunctionBegin;
8296552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8297dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
8298552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
82993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8300552f7358SJed Brown }
8301552f7358SJed Brown 
83027cd05799SMatthew G. Knepley /*@C
83037cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
83047cd05799SMatthew G. Knepley 
83057cd05799SMatthew G. Knepley   Input Parameters:
8306a1cb98faSBarry Smith + dm   - The `DMPLEX` object
83077cd05799SMatthew G. Knepley - cellHeight - The height of a cell
83087cd05799SMatthew G. Knepley 
83097cd05799SMatthew G. Knepley   Level: developer
83107cd05799SMatthew G. Knepley 
83111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
83127cd05799SMatthew G. Knepley @*/
8313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8314d71ae5a4SJacob Faibussowitsch {
8315552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8316552f7358SJed Brown 
8317552f7358SJed Brown   PetscFunctionBegin;
8318552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8319552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
83203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8321552f7358SJed Brown }
8322552f7358SJed Brown 
8323e6139122SMatthew G. Knepley /*@
8324e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
8325e6139122SMatthew G. Knepley 
8326e6139122SMatthew G. Knepley   Input Parameter:
8327a1cb98faSBarry Smith . dm - The `DMPLEX` object
8328e6139122SMatthew G. Knepley 
8329e6139122SMatthew G. Knepley   Output Parameters:
833020f4b53cSBarry Smith + gcStart - The first ghost cell, or `NULL`
833120f4b53cSBarry Smith - gcEnd   - The upper bound on ghost cells, or `NULL`
8332e6139122SMatthew G. Knepley 
83332a9f31c0SMatthew G. Knepley   Level: advanced
8334e6139122SMatthew G. Knepley 
83351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
8336e6139122SMatthew G. Knepley @*/
8337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8338d71ae5a4SJacob Faibussowitsch {
8339412e9a14SMatthew G. Knepley   DMLabel ctLabel;
8340e6139122SMatthew G. Knepley 
8341e6139122SMatthew G. Knepley   PetscFunctionBegin;
8342e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
83449566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8345695799ffSMatthew G. Knepley   // Reset label for fast lookup
8346695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
83473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8348e6139122SMatthew G. Knepley }
8349e6139122SMatthew G. Knepley 
8350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8351d71ae5a4SJacob Faibussowitsch {
8352552f7358SJed Brown   PetscSection section, globalSection;
8353552f7358SJed Brown   PetscInt    *numbers, p;
8354552f7358SJed Brown 
8355552f7358SJed Brown   PetscFunctionBegin;
8356d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
83579566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
83589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
835948a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
83609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
83619566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
83629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8363552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
83649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8365ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8366ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8367552f7358SJed Brown   }
83689566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8369ef48cebcSMatthew G. Knepley   if (globalSize) {
8370ef48cebcSMatthew G. Knepley     PetscLayout layout;
83719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
83729566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
83739566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8374ef48cebcSMatthew G. Knepley   }
83759566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
83769566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
83773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8378552f7358SJed Brown }
8379552f7358SJed Brown 
8380d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8381d71ae5a4SJacob Faibussowitsch {
8382412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8383552f7358SJed Brown 
8384552f7358SJed Brown   PetscFunctionBegin;
83859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
83869566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
83879566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
83889566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
83893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8390552f7358SJed Brown }
839181ed3555SMatthew G. Knepley 
83928dab3259SMatthew G. Knepley /*@
83937cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
83947cd05799SMatthew G. Knepley 
83957cd05799SMatthew G. Knepley   Input Parameter:
8396a1cb98faSBarry Smith . dm   - The `DMPLEX` object
83977cd05799SMatthew G. Knepley 
83987cd05799SMatthew G. Knepley   Output Parameter:
83997cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
84007cd05799SMatthew G. Knepley 
84017cd05799SMatthew G. Knepley   Level: developer
84027cd05799SMatthew G. Knepley 
84031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
84047cd05799SMatthew G. Knepley @*/
8405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8406d71ae5a4SJacob Faibussowitsch {
840781ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
840881ed3555SMatthew G. Knepley 
840981ed3555SMatthew G. Knepley   PetscFunctionBegin;
841081ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84119566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8412552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
84133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8414552f7358SJed Brown }
8415552f7358SJed Brown 
8416d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8417d71ae5a4SJacob Faibussowitsch {
8418412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
841981ed3555SMatthew G. Knepley 
842081ed3555SMatthew G. Knepley   PetscFunctionBegin;
842181ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
84239566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
84243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
842581ed3555SMatthew G. Knepley }
842681ed3555SMatthew G. Knepley 
84278dab3259SMatthew G. Knepley /*@
84286aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
84297cd05799SMatthew G. Knepley 
84307cd05799SMatthew G. Knepley   Input Parameter:
8431a1cb98faSBarry Smith . dm   - The `DMPLEX` object
84327cd05799SMatthew G. Knepley 
84337cd05799SMatthew G. Knepley   Output Parameter:
84347cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
84357cd05799SMatthew G. Knepley 
84367cd05799SMatthew G. Knepley   Level: developer
84377cd05799SMatthew G. Knepley 
84381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
84397cd05799SMatthew G. Knepley @*/
8440d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8441d71ae5a4SJacob Faibussowitsch {
8442552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8443552f7358SJed Brown 
8444552f7358SJed Brown   PetscFunctionBegin;
8445552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84469566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8447552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
84483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8449552f7358SJed Brown }
8450552f7358SJed Brown 
84518dab3259SMatthew G. Knepley /*@
8452966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8453966484cfSJed Brown 
845420f4b53cSBarry Smith   Collective
84557cd05799SMatthew G. Knepley 
84567cd05799SMatthew G. Knepley   Input Parameter:
8457a1cb98faSBarry Smith . dm   - The `DMPLEX` object
84587cd05799SMatthew G. Knepley 
84597cd05799SMatthew G. Knepley   Output Parameter:
84607cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
84617cd05799SMatthew G. Knepley 
8462a1cb98faSBarry Smith   Level: developer
8463966484cfSJed Brown 
8464a1cb98faSBarry Smith   Notes:
8465a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8466966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8467966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8468966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8469966484cfSJed Brown 
8470966484cfSJed Brown   The partitioned mesh is
8471966484cfSJed Brown ```
8472966484cfSJed Brown  (2)--0--(3)--1--(4)    (1)--0--(2)
8473966484cfSJed Brown ```
8474966484cfSJed Brown   and its global numbering is
8475966484cfSJed Brown ```
8476966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8477966484cfSJed Brown ```
8478966484cfSJed Brown   Then the global numbering is provided as
8479966484cfSJed Brown ```
8480966484cfSJed Brown [0] Number of indices in set 5
8481966484cfSJed Brown [0] 0 0
8482966484cfSJed Brown [0] 1 1
8483966484cfSJed Brown [0] 2 3
8484966484cfSJed Brown [0] 3 4
8485966484cfSJed Brown [0] 4 -6
8486966484cfSJed Brown [1] Number of indices in set 3
8487966484cfSJed Brown [1] 0 2
8488966484cfSJed Brown [1] 1 5
8489966484cfSJed Brown [1] 2 6
8490966484cfSJed Brown ```
8491966484cfSJed Brown 
84921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
84937cd05799SMatthew G. Knepley @*/
8494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8495d71ae5a4SJacob Faibussowitsch {
8496ef48cebcSMatthew G. Knepley   IS        nums[4];
8497862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8498ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
84990c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8500ef48cebcSMatthew G. Knepley 
8501ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8502ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
85040c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
85059566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
85060c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8507862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8508862913ffSStefano Zampini     PetscInt end;
8509862913ffSStefano Zampini 
8510862913ffSStefano Zampini     depths[d] = depth - d;
85119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
85120c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8513862913ffSStefano Zampini   }
85140c15888dSMatthew G. Knepley   if (empty)
85150c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
85160c15888dSMatthew G. Knepley       depths[d] = -1;
85170c15888dSMatthew G. Knepley       starts[d] = -1;
85180c15888dSMatthew G. Knepley     }
85190c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
85201c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8521ad540459SPierre 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]);
85220c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8523ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8524ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8525ef48cebcSMatthew G. Knepley 
85269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
85279566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8528ef48cebcSMatthew G. Knepley     shift += gsize;
8529ef48cebcSMatthew G. Knepley   }
8530d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
85319566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
85323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8533ef48cebcSMatthew G. Knepley }
8534ef48cebcSMatthew G. Knepley 
853508a22f4bSMatthew G. Knepley /*@
853608a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
853708a22f4bSMatthew G. Knepley 
853808a22f4bSMatthew G. Knepley   Input Parameter:
8539a1cb98faSBarry Smith . dm - The `DMPLEX` object
854008a22f4bSMatthew G. Knepley 
854108a22f4bSMatthew G. Knepley   Output Parameter:
854208a22f4bSMatthew G. Knepley . ranks - The rank field
854308a22f4bSMatthew G. Knepley 
8544a1cb98faSBarry Smith   Options Database Key:
854520f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
854608a22f4bSMatthew G. Knepley 
854708a22f4bSMatthew G. Knepley   Level: intermediate
854808a22f4bSMatthew G. Knepley 
85491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
855008a22f4bSMatthew G. Knepley @*/
8551d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8552d71ae5a4SJacob Faibussowitsch {
855308a22f4bSMatthew G. Knepley   DM             rdm;
855408a22f4bSMatthew G. Knepley   PetscFE        fe;
855508a22f4bSMatthew G. Knepley   PetscScalar   *r;
855608a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8557a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
855808a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8559a55f9a55SMatthew G. Knepley   PetscBool      simplex;
856008a22f4bSMatthew G. Knepley 
856108a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8562f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8563f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
85649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
85659566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
85669566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
85679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
85689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8569a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
85709566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
85719566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
85729566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
85739566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85749566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
85759566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
85769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
85779566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
857808a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
857908a22f4bSMatthew G. Knepley     PetscScalar *lr;
858008a22f4bSMatthew G. Knepley 
85819566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
858271f09efeSPierre Jolivet     if (lr) *lr = rank;
858308a22f4bSMatthew G. Knepley   }
85849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
85859566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
85863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
858708a22f4bSMatthew G. Knepley }
858808a22f4bSMatthew G. Knepley 
8589ca8062c8SMatthew G. Knepley /*@
859018e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
859118e14f0cSMatthew G. Knepley 
859218e14f0cSMatthew G. Knepley   Input Parameters:
859320f4b53cSBarry Smith + dm    - The `DMPLEX`
859420f4b53cSBarry Smith - label - The `DMLabel`
859518e14f0cSMatthew G. Knepley 
859618e14f0cSMatthew G. Knepley   Output Parameter:
859718e14f0cSMatthew G. Knepley . val - The label value field
859818e14f0cSMatthew G. Knepley 
859920f4b53cSBarry Smith   Options Database Key:
860020f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
860118e14f0cSMatthew G. Knepley 
860218e14f0cSMatthew G. Knepley   Level: intermediate
860318e14f0cSMatthew G. Knepley 
86041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
860518e14f0cSMatthew G. Knepley @*/
8606d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8607d71ae5a4SJacob Faibussowitsch {
860818e14f0cSMatthew G. Knepley   DM           rdm;
860918e14f0cSMatthew G. Knepley   PetscFE      fe;
861018e14f0cSMatthew G. Knepley   PetscScalar *v;
861118e14f0cSMatthew G. Knepley   PetscInt     dim, cStart, cEnd, c;
861218e14f0cSMatthew G. Knepley 
861318e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
861418e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
861518e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
861618e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
86179566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
86189566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
86199566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
86209566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "label_value"));
86219566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
86229566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
86239566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
86249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
86259566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
86269566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*val, "label_value"));
86279566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
862818e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
862918e14f0cSMatthew G. Knepley     PetscScalar *lv;
863018e14f0cSMatthew G. Knepley     PetscInt     cval;
863118e14f0cSMatthew G. Knepley 
86329566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
86339566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
863418e14f0cSMatthew G. Knepley     *lv = cval;
863518e14f0cSMatthew G. Knepley   }
86369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
86379566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
86383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
863918e14f0cSMatthew G. Knepley }
864018e14f0cSMatthew G. Knepley 
864118e14f0cSMatthew G. Knepley /*@
8642ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8643ca8062c8SMatthew G. Knepley 
864469916449SMatthew G. Knepley   Input Parameter:
8645a1cb98faSBarry Smith . dm - The `DMPLEX` object
8646a1cb98faSBarry Smith 
8647a1cb98faSBarry Smith   Level: developer
8648ca8062c8SMatthew G. Knepley 
864995eb5ee5SVaclav Hapla   Notes:
865095eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
865195eb5ee5SVaclav Hapla 
865220f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8653ca8062c8SMatthew G. Knepley 
86541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8655ca8062c8SMatthew G. Knepley @*/
8656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8657d71ae5a4SJacob Faibussowitsch {
8658ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8659ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8660ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
866157beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
866257beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8663ca8062c8SMatthew G. Knepley 
8664ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8665ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86669566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
86679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
86689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8669ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
86709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8671ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
86729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
86739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8674ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
867542e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
867642e66dfaSMatthew G. Knepley       PetscInt  d;
867742e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
86789371c9d4SSatish Balay         if (cone[c] == cone[d]) {
86799371c9d4SSatish Balay           dup = PETSC_TRUE;
86809371c9d4SSatish Balay           break;
86819371c9d4SSatish Balay         }
868242e66dfaSMatthew G. Knepley       }
86839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
86849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8685ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8686ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8687ca8062c8SMatthew G. Knepley       }
868842e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
868963a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
869048a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
86919566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
869263a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
869348a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
86949566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
869563a3b9bcSJacob 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]);
8696f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8697ca8062c8SMatthew G. Knepley       }
869842e66dfaSMatthew G. Knepley     }
86999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
87009371c9d4SSatish Balay     if (p != pp) {
87019371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
87029371c9d4SSatish Balay       continue;
87039371c9d4SSatish Balay     }
87049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
87059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8706ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
87079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
87089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8709ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
87109566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
87119371c9d4SSatish Balay         if (cone[c] != pp) {
87129371c9d4SSatish Balay           c = 0;
87139371c9d4SSatish Balay           break;
87149371c9d4SSatish Balay         }
8715ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8716ca8062c8SMatthew G. Knepley       }
8717ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
871863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
871948a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
87209566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
872163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
872248a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
87239566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
872463a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8725ca8062c8SMatthew G. Knepley       }
8726ca8062c8SMatthew G. Knepley     }
8727ca8062c8SMatthew G. Knepley   }
872857beb4faSStefano Zampini   if (storagecheck) {
87299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
87309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
873163a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
873257beb4faSStefano Zampini   }
87333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8734ca8062c8SMatthew G. Knepley }
8735ca8062c8SMatthew G. Knepley 
8736412e9a14SMatthew G. Knepley /*
8737412e9a14SMatthew 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.
8738412e9a14SMatthew G. Knepley */
8739d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8740d71ae5a4SJacob Faibussowitsch {
8741412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8742412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8743412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8744412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8745412e9a14SMatthew G. Knepley 
8746412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8747412e9a14SMatthew G. Knepley   *unsplit = 0;
8748412e9a14SMatthew G. Knepley   switch (ct) {
8749d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
8750d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
8751d71ae5a4SJacob Faibussowitsch     break;
8752412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
87539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8755412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8757412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8758412e9a14SMatthew G. Knepley     }
8759412e9a14SMatthew G. Knepley     break;
8760412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
8761412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
87629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8764412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
87669566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8767412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
87689566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8769412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8770412e9a14SMatthew G. Knepley           PetscInt p;
87719371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
87729371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
8773412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
8774412e9a14SMatthew G. Knepley         }
8775412e9a14SMatthew G. Knepley       }
8776412e9a14SMatthew G. Knepley     }
8777412e9a14SMatthew G. Knepley     break;
8778d71ae5a4SJacob Faibussowitsch   default:
8779d71ae5a4SJacob Faibussowitsch     break;
8780412e9a14SMatthew G. Knepley   }
8781412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
87829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8783412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8784412e9a14SMatthew G. Knepley   }
87853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8786412e9a14SMatthew G. Knepley }
8787412e9a14SMatthew G. Knepley 
8788ca8062c8SMatthew G. Knepley /*@
8789ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8790ca8062c8SMatthew G. Knepley 
8791ca8062c8SMatthew G. Knepley   Input Parameters:
8792a1cb98faSBarry Smith + dm - The `DMPLEX` object
879358723a97SMatthew G. Knepley - cellHeight - Normally 0
8794ca8062c8SMatthew G. Knepley 
8795a1cb98faSBarry Smith   Level: developer
8796a1cb98faSBarry Smith 
879795eb5ee5SVaclav Hapla   Notes:
879895eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
879925c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8800ca8062c8SMatthew G. Knepley 
880120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
880295eb5ee5SVaclav Hapla 
88031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8804ca8062c8SMatthew G. Knepley @*/
8805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8806d71ae5a4SJacob Faibussowitsch {
8807412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8808412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8809412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8810ca8062c8SMatthew G. Knepley 
8811ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8812ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88139566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
88149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
88159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8816412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8817412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8818412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
881958723a97SMatthew G. Knepley 
88209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
882163a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8822412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8823412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
88249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
882563a3b9bcSJacob 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));
8826412e9a14SMatthew G. Knepley     }
88279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
882858723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
882958723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8830412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
883158723a97SMatthew G. Knepley     }
88329566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8833412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8834412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8835412e9a14SMatthew G. Knepley       PetscInt unsplit;
883642363296SMatthew G. Knepley 
88379566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8838412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
883942363296SMatthew G. Knepley     }
884063a3b9bcSJacob 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));
884142363296SMatthew G. Knepley   }
88423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8843ca8062c8SMatthew G. Knepley }
88449bf0dad6SMatthew G. Knepley 
88459bf0dad6SMatthew G. Knepley /*@
88469bf0dad6SMatthew 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
88479bf0dad6SMatthew G. Knepley 
884820f4b53cSBarry Smith   Collective
8849899ea2b8SJacob Faibussowitsch 
88509bf0dad6SMatthew G. Knepley   Input Parameters:
8851a1cb98faSBarry Smith + dm - The `DMPLEX` object
88529bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
88539bf0dad6SMatthew G. Knepley 
8854a1cb98faSBarry Smith   Level: developer
8855a1cb98faSBarry Smith 
885645da879fSVaclav Hapla   Notes:
885745da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
885845da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
885945da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
886045da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
88619bf0dad6SMatthew G. Knepley 
8862a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
886395eb5ee5SVaclav Hapla 
88641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
88659bf0dad6SMatthew G. Knepley @*/
8866d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
8867d71ae5a4SJacob Faibussowitsch {
8868ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8869899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
88709bf0dad6SMatthew G. Knepley 
88719bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
88729bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88738f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
88743ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
88758f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
88763ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
88773ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8878899ea2b8SJacob Faibussowitsch   }
8879899ea2b8SJacob Faibussowitsch 
88809566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
88819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
88829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8883ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
88849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
88853554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8886412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
8887412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8888ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8889412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8890412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
88919bf0dad6SMatthew G. Knepley 
88929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
88939566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8894412e9a14SMatthew G. Knepley       if (unsplit) continue;
88959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
88969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
88979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
88989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
88999bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
89009bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
89019bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
89029bf0dad6SMatthew G. Knepley       }
89039566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
890463a3b9bcSJacob 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);
89059bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8906d4961f80SStefano Zampini         DMPolytopeType fct;
89079bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
89089bf0dad6SMatthew G. Knepley 
89099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
89109566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
89119bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
89129bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
89139bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
89149bf0dad6SMatthew G. Knepley         }
891563a3b9bcSJacob 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]);
89169bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8917b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
8918b5a892a1SMatthew G. Knepley             PetscInt v1;
8919b5a892a1SMatthew G. Knepley 
89209566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
892163a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
89229566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
892363a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
89249566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
892563a3b9bcSJacob 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]);
8926b5a892a1SMatthew G. Knepley           }
89279bf0dad6SMatthew G. Knepley         }
89289566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8929412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
89309bf0dad6SMatthew G. Knepley       }
89319566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
89329566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
89339bf0dad6SMatthew G. Knepley     }
89343554e41dSMatthew G. Knepley   }
89353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8936552f7358SJed Brown }
89373913d7c8SMatthew G. Knepley 
8938bb6a34a8SMatthew G. Knepley /*@
8939bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8940bb6a34a8SMatthew G. Knepley 
8941bb6a34a8SMatthew G. Knepley   Input Parameter:
8942a1cb98faSBarry Smith . dm - The `DMPLEX` object
8943a1cb98faSBarry Smith 
8944a1cb98faSBarry Smith   Level: developer
8945bb6a34a8SMatthew G. Knepley 
894695eb5ee5SVaclav Hapla   Notes:
894795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
894895eb5ee5SVaclav Hapla 
894920f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8950bb6a34a8SMatthew G. Knepley 
89511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8952bb6a34a8SMatthew G. Knepley @*/
8953d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
8954d71ae5a4SJacob Faibussowitsch {
8955a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8956bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8957bb6a34a8SMatthew G. Knepley   PetscReal vol;
895851a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8959bb6a34a8SMatthew G. Knepley 
8960bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
89619566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
89629566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
89633ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
89649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8965bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
89669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8967a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
89689566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
89693ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
8970412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8971412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8972412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8973412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8974412e9a14SMatthew G. Knepley 
89759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8976412e9a14SMatthew G. Knepley     switch (ct) {
8977412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8978412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8979d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8980d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
8981d71ae5a4SJacob Faibussowitsch       break;
8982d71ae5a4SJacob Faibussowitsch     default:
8983d71ae5a4SJacob Faibussowitsch       break;
8984412e9a14SMatthew G. Knepley     }
8985412e9a14SMatthew G. Knepley     switch (ct) {
8986412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
8987412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8988412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8989d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
8990d71ae5a4SJacob Faibussowitsch       continue;
8991d71ae5a4SJacob Faibussowitsch     default:
8992d71ae5a4SJacob Faibussowitsch       break;
8993412e9a14SMatthew G. Knepley     }
89949566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8995412e9a14SMatthew G. Knepley     if (unsplit) continue;
89969566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
89971dca8a05SBarry 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);
899863a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
89996858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
90006858538eSMatthew G. Knepley     if (depth > 1) {
90019566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
90021dca8a05SBarry 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);
900363a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9004bb6a34a8SMatthew G. Knepley     }
9005bb6a34a8SMatthew G. Knepley   }
90063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9007bb6a34a8SMatthew G. Knepley }
9008bb6a34a8SMatthew G. Knepley 
900903da9461SVaclav Hapla /*@
901020f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
90117726db96SVaclav Hapla 
901220f4b53cSBarry Smith   Collective
901303da9461SVaclav Hapla 
901403da9461SVaclav Hapla   Input Parameters:
9015a1cb98faSBarry Smith + dm - The `DMPLEX` object
901620f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9017a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9018a1cb98faSBarry Smith 
9019a1cb98faSBarry Smith   Level: developer
902003da9461SVaclav Hapla 
9021e83a0d2dSVaclav Hapla   Notes:
9022e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
902303da9461SVaclav Hapla 
9024a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
902595eb5ee5SVaclav Hapla 
9026d7d32a9aSMatthew G. Knepley   Extra roots can come from priodic cuts, where additional points appear on the boundary
9027d7d32a9aSMatthew G. Knepley 
90281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
902903da9461SVaclav Hapla @*/
9030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9031d71ae5a4SJacob Faibussowitsch {
90327726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
90337726db96SVaclav Hapla   const PetscInt    *locals;
90347726db96SVaclav Hapla   const PetscSFNode *remotes;
9035f0cfc026SVaclav Hapla   PetscBool          distributed;
90367726db96SVaclav Hapla   MPI_Comm           comm;
90377726db96SVaclav Hapla   PetscMPIInt        rank;
903803da9461SVaclav Hapla 
903903da9461SVaclav Hapla   PetscFunctionBegin;
904003da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90417726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
90427726db96SVaclav Hapla   else pointSF = dm->sf;
90437726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
90447726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
90457726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
90467726db96SVaclav Hapla   {
90477726db96SVaclav Hapla     PetscMPIInt mpiFlag;
90487726db96SVaclav Hapla 
90497726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
90507726db96SVaclav 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);
90517726db96SVaclav Hapla   }
90527726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
90539566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
90547726db96SVaclav Hapla   if (!distributed) {
90557726db96SVaclav 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);
90563ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
90578918e3e2SVaclav Hapla   }
90587726db96SVaclav 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);
90597726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
906003da9461SVaclav Hapla 
90617726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
90627726db96SVaclav Hapla   {
90637726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
90647726db96SVaclav Hapla 
90657726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
90667726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9067d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
90687726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
90697726db96SVaclav Hapla   }
90707726db96SVaclav Hapla 
90717726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
90727726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
90737726db96SVaclav 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);
90747726db96SVaclav Hapla   }
90757726db96SVaclav Hapla 
90767726db96SVaclav Hapla   /* Check there are no cells in interface */
90777726db96SVaclav Hapla   if (!overlap) {
90787726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
90797726db96SVaclav Hapla 
90809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9082f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
90837726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9084f5869d18SMatthew G. Knepley 
90857726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
90867726db96SVaclav Hapla     }
908703da9461SVaclav Hapla   }
9088ece87651SVaclav Hapla 
90897726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
90907726db96SVaclav Hapla   {
90917726db96SVaclav Hapla     const PetscInt *rootdegree;
90927726db96SVaclav Hapla 
90937726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
90947726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9095f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
90967726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9097f5869d18SMatthew G. Knepley       const PetscInt *cone;
9098f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9099f5869d18SMatthew G. Knepley 
91009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
91019566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9102f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9103f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
91047726db96SVaclav Hapla           if (locals) {
91059566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
91067726db96SVaclav Hapla           } else {
91077726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
91087726db96SVaclav Hapla           }
910963a3b9bcSJacob 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]);
9110f5869d18SMatthew G. Knepley         }
9111f5869d18SMatthew G. Knepley       }
9112ece87651SVaclav Hapla     }
91137726db96SVaclav Hapla   }
91143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
911503da9461SVaclav Hapla }
911603da9461SVaclav Hapla 
91177f9d8d6cSVaclav Hapla /*@
911820f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
91197f9d8d6cSVaclav Hapla 
91207f9d8d6cSVaclav Hapla   Input Parameter:
9121a1cb98faSBarry Smith . dm - The `DMPLEX` object
9122a1cb98faSBarry Smith 
9123a1cb98faSBarry Smith   Level: developer
91247f9d8d6cSVaclav Hapla 
91257f9d8d6cSVaclav Hapla   Notes:
91267f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
91277f9d8d6cSVaclav Hapla 
912820f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
91297f9d8d6cSVaclav Hapla 
913020f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
91317f9d8d6cSVaclav Hapla 
91321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
91337f9d8d6cSVaclav Hapla @*/
9134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9135d71ae5a4SJacob Faibussowitsch {
91367f9d8d6cSVaclav Hapla   PetscInt cellHeight;
91377f9d8d6cSVaclav Hapla 
9138b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91397f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
91409566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
91419566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
91429566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
91439566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9144d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
91459566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
91463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9147b5a892a1SMatthew G. Knepley }
9148b5a892a1SMatthew G. Knepley 
91499371c9d4SSatish Balay typedef struct cell_stats {
9150068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9151068a5610SStefano Zampini   PetscInt  count;
9152068a5610SStefano Zampini } cell_stats_t;
9153068a5610SStefano Zampini 
9154d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9155d71ae5a4SJacob Faibussowitsch {
9156068a5610SStefano Zampini   PetscInt i, N = *len;
9157068a5610SStefano Zampini 
9158068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9159068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9160068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9161068a5610SStefano Zampini 
9162068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9163068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9164068a5610SStefano Zampini     B->sum += A->sum;
9165068a5610SStefano Zampini     B->squaresum += A->squaresum;
9166068a5610SStefano Zampini     B->count += A->count;
9167068a5610SStefano Zampini   }
9168068a5610SStefano Zampini }
9169068a5610SStefano Zampini 
9170068a5610SStefano Zampini /*@
917143fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9172068a5610SStefano Zampini 
917320f4b53cSBarry Smith   Collective
91748261a58bSMatthew G. Knepley 
9175068a5610SStefano Zampini   Input Parameters:
9176a1cb98faSBarry Smith + dm        - The `DMPLEX` object
917720f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9178a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9179a1cb98faSBarry Smith 
9180a1cb98faSBarry Smith   Level: developer
9181068a5610SStefano Zampini 
918295eb5ee5SVaclav Hapla   Notes:
918395eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
918495eb5ee5SVaclav Hapla 
9185a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9186068a5610SStefano Zampini 
91871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9188068a5610SStefano Zampini @*/
9189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9190d71ae5a4SJacob Faibussowitsch {
9191068a5610SStefano Zampini   DM           dmCoarse;
919243fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
919343fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
919443fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
919543fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9196412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
919743fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9198068a5610SStefano Zampini 
9199068a5610SStefano Zampini   PetscFunctionBegin;
9200068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9201068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9202068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9203068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9204068a5610SStefano Zampini   stats.count                 = 0;
9205068a5610SStefano Zampini 
92069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
92079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
92089566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
92099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
92109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
92119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9212412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9213068a5610SStefano Zampini     PetscInt  i;
9214068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9215068a5610SStefano Zampini 
92169566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
921763a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
921843fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9219068a5610SStefano Zampini       frobJ += J[i] * J[i];
9220068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9221068a5610SStefano Zampini     }
9222068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9223068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9224068a5610SStefano Zampini 
9225068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9226068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9227068a5610SStefano Zampini     stats.sum += cond;
9228068a5610SStefano Zampini     stats.squaresum += cond2;
9229068a5610SStefano Zampini     stats.count++;
92308261a58bSMatthew G. Knepley     if (output && cond > limit) {
923143fa8764SMatthew G. Knepley       PetscSection coordSection;
923243fa8764SMatthew G. Knepley       Vec          coordsLocal;
923343fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
923443fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
923543fa8764SMatthew G. Knepley 
92369566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
92379566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
92389566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
923963a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
924043fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
924163a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
924243fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
92439566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
92449566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
924543fa8764SMatthew G. Knepley         }
92469566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
924743fa8764SMatthew G. Knepley       }
92489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
924943fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
925043fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
925143fa8764SMatthew G. Knepley 
925243fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
925343fa8764SMatthew G. Knepley           PetscReal len;
925443fa8764SMatthew G. Knepley 
92559566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
925663a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
925743fa8764SMatthew G. Knepley         }
925843fa8764SMatthew G. Knepley       }
92599566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
92609566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
926143fa8764SMatthew G. Knepley     }
9262068a5610SStefano Zampini   }
92639566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9264068a5610SStefano Zampini 
9265068a5610SStefano Zampini   if (size > 1) {
9266068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9267068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9268068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9269068a5610SStefano Zampini     MPI_Op       statReduce;
9270068a5610SStefano Zampini 
92719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
92729566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
92739566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
92749566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
92759566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
92769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9277068a5610SStefano Zampini   } else {
92789566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9279068a5610SStefano Zampini   }
9280dd400576SPatrick Sanan   if (rank == 0) {
9281068a5610SStefano Zampini     count = globalStats.count;
9282068a5610SStefano Zampini     min   = globalStats.min;
9283068a5610SStefano Zampini     max   = globalStats.max;
9284068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9285068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9286068a5610SStefano Zampini   }
9287068a5610SStefano Zampini 
928848a46eb9SPierre 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));
92899566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9290068a5610SStefano Zampini 
92919566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9292068a5610SStefano Zampini   if (dmCoarse) {
9293068a5610SStefano Zampini     PetscBool isplex;
9294068a5610SStefano Zampini 
92959566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
92961baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9297068a5610SStefano Zampini   }
92983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9299068a5610SStefano Zampini }
9300068a5610SStefano Zampini 
9301f108dbd7SJacob Faibussowitsch /*@
9302f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9303f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9304f108dbd7SJacob Faibussowitsch 
930520f4b53cSBarry Smith   Collective
9306f108dbd7SJacob Faibussowitsch 
9307f108dbd7SJacob Faibussowitsch   Input Parameters:
9308a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9309a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9310f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9311f108dbd7SJacob Faibussowitsch 
9312f108dbd7SJacob Faibussowitsch   Output Parameters:
931320f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9314a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9315f108dbd7SJacob Faibussowitsch 
9316f108dbd7SJacob Faibussowitsch   Options Database Keys:
9317a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9318f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
9319f108dbd7SJacob Faibussowitsch 
9320a1cb98faSBarry Smith   Level: intermediate
9321a1cb98faSBarry Smith 
9322f108dbd7SJacob Faibussowitsch   Notes:
9323f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
9324f108dbd7SJacob Faibussowitsch 
9325a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9326f108dbd7SJacob Faibussowitsch 
9327f108dbd7SJacob 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
9328f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9329f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9330f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9331f108dbd7SJacob Faibussowitsch 
9332f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9333f108dbd7SJacob Faibussowitsch 
9334a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9335f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9336f108dbd7SJacob Faibussowitsch 
9337f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9338f108dbd7SJacob Faibussowitsch 
93391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9340f108dbd7SJacob Faibussowitsch @*/
9341d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9342d71ae5a4SJacob Faibussowitsch {
93436ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
93446ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
93456ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9346f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
93476ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9348f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9349f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9350f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9351f108dbd7SJacob Faibussowitsch   IS                     glob;
9352f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9353f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9354f108dbd7SJacob Faibussowitsch 
9355f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9356f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9357ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
9358f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
93596bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
93609566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
93619566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
936263a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
93636ed19f2fSJacob Faibussowitsch   {
93646ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
93656ed19f2fSJacob Faibussowitsch 
93669566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9367f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9368f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9369f108dbd7SJacob Faibussowitsch 
93709566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
937198921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9372f108dbd7SJacob Faibussowitsch     }
93736ed19f2fSJacob Faibussowitsch   }
9374f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
9375f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
93769566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
93779566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
93789371c9d4SSatish Balay   } else {
93799371c9d4SSatish Balay     *OrthQualLabel = NULL;
93809371c9d4SSatish Balay   }
93819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
93829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
93839566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
93849566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
93859566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
93869566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
93879566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
93889566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
93899566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
93909566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
93919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
93929566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
93939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
93949566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
93959566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
93969566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
93979566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
93989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
93996ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
94006ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9401f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9402f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9403898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9404f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9405f108dbd7SJacob Faibussowitsch 
94066ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9407f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9408f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
94099566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
94109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9411f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
94129566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
94136ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
94146ed19f2fSJacob Faibussowitsch       PetscInt         i;
94156ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9416f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9417f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9418f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9419f108dbd7SJacob Faibussowitsch 
9420f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9421f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
94229566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9423f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
94246ed19f2fSJacob Faibussowitsch       {
94256ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
94266ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
94276ed19f2fSJacob Faibussowitsch 
94289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
94299566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
94309566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
94316ed19f2fSJacob Faibussowitsch       }
9432f108dbd7SJacob Faibussowitsch 
9433f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9434f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9435f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9436f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9437f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9438addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9439addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9440addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9441f108dbd7SJacob Faibussowitsch       }
9442addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9443addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9444addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9445f108dbd7SJacob Faibussowitsch 
9446f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9447f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9448f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9449f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9450f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9451f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9452f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9453f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9454f108dbd7SJacob Faibussowitsch       }
9455ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9456ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9457f108dbd7SJacob Faibussowitsch     }
94589566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
94599566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9460f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
94616ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9462f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
94639566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9464f108dbd7SJacob Faibussowitsch     }
9465f108dbd7SJacob Faibussowitsch   }
94669566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
94679566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
94689566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
94699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
94709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
94719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9472f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
94739566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9474f108dbd7SJacob Faibussowitsch   }
94759566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
94769566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
94779566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
94783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9479f108dbd7SJacob Faibussowitsch }
9480f108dbd7SJacob Faibussowitsch 
9481d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
94821eb70e55SToby Isaac  * interpolator construction */
9483d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9484d71ae5a4SJacob Faibussowitsch {
94851eb70e55SToby Isaac   PetscSection section, newSection, gsection;
94861eb70e55SToby Isaac   PetscSF      sf;
94871eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
94881eb70e55SToby Isaac 
94891eb70e55SToby Isaac   PetscFunctionBegin;
94901eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94911eb70e55SToby Isaac   PetscValidPointer(odm, 2);
94929566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
94939566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9494712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
94951eb70e55SToby Isaac   if (!ghasConstraints) {
94969566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
94971eb70e55SToby Isaac     *odm = dm;
94983ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
94991eb70e55SToby Isaac   }
95009566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
95019566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
95029566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
95039566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
95049566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
95059566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
95069566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
95073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95081eb70e55SToby Isaac }
95091eb70e55SToby Isaac 
9510d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9511d71ae5a4SJacob Faibussowitsch {
95121eb70e55SToby Isaac   DM        dmco, dmfo;
95131eb70e55SToby Isaac   Mat       interpo;
95141eb70e55SToby Isaac   Vec       rscale;
95151eb70e55SToby Isaac   Vec       cglobalo, clocal;
95161eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
95171eb70e55SToby Isaac   PetscBool regular;
95181eb70e55SToby Isaac 
95191eb70e55SToby Isaac   PetscFunctionBegin;
95209566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
95219566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
95229566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
95239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
95249566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
95259566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
95269566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
95279566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
95289566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
95299566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
95309566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
95319566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
95329566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
95339566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
95349566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
95359566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
95369566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
95379566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
95389566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
95399566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
95409566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
95419566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
95429566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
95439566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
95441eb70e55SToby Isaac   *shift = fglobal;
95459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
95469566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
95479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
95489566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
95499566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
95509566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
95519566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
95529566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
95533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95541eb70e55SToby Isaac }
95551eb70e55SToby Isaac 
9556d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9557d71ae5a4SJacob Faibussowitsch {
95581eb70e55SToby Isaac   PetscObject shifto;
95591eb70e55SToby Isaac   Vec         shift;
95601eb70e55SToby Isaac 
95611eb70e55SToby Isaac   PetscFunctionBegin;
95621eb70e55SToby Isaac   if (!interp) {
95631eb70e55SToby Isaac     Vec rscale;
95641eb70e55SToby Isaac 
95659566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
95669566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
95671eb70e55SToby Isaac   } else {
95689566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
95691eb70e55SToby Isaac   }
95709566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
95711eb70e55SToby Isaac   if (!shifto) {
95729566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
95739566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
95741eb70e55SToby Isaac     shifto = (PetscObject)shift;
95759566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
95761eb70e55SToby Isaac   }
95771eb70e55SToby Isaac   shift = (Vec)shifto;
95789566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
95799566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
95809566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
95813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95821eb70e55SToby Isaac }
95831eb70e55SToby Isaac 
9584bceba477SMatthew G. Knepley /* Pointwise interpolation
9585bceba477SMatthew G. Knepley      Just code FEM for now
9586bceba477SMatthew G. Knepley      u^f = I u^c
95874ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
95884ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
95894ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9590bceba477SMatthew G. Knepley */
9591d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9592d71ae5a4SJacob Faibussowitsch {
9593bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9594bceba477SMatthew G. Knepley   PetscInt     m, n;
9595a063dac3SMatthew G. Knepley   void        *ctx;
959668132eb9SMatthew G. Knepley   DM           cdm;
9597cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9598bceba477SMatthew G. Knepley 
9599bceba477SMatthew G. Knepley   PetscFunctionBegin;
96009566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
96019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
96029566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
96039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
960468132eb9SMatthew G. Knepley 
96059566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
96069566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
96079566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
96089566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
96099566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
961068132eb9SMatthew G. Knepley 
96119566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
96129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
96139566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
96149566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
96159566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
96164db47ee9SStefano Zampini   if (scaling) {
96175d1c2e58SMatthew G. Knepley     /* Use naive scaling */
96189566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
96194db47ee9SStefano Zampini   }
96203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9621a063dac3SMatthew G. Knepley }
9622bceba477SMatthew G. Knepley 
9623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9624d71ae5a4SJacob Faibussowitsch {
96256dbf9973SLawrence Mitchell   VecScatter ctx;
962690748bafSMatthew G. Knepley 
9627a063dac3SMatthew G. Knepley   PetscFunctionBegin;
96289566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
96299566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
96309566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
96313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9632bceba477SMatthew G. Knepley }
9633bceba477SMatthew G. Knepley 
9634d71ae5a4SJacob 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[])
9635d71ae5a4SJacob Faibussowitsch {
963600635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
963700635df3SMatthew G. Knepley   PetscInt       c;
963800635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
96393e9753d6SMatthew G. Knepley }
96403e9753d6SMatthew G. Knepley 
9641d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9642d71ae5a4SJacob Faibussowitsch {
9643b4937a87SMatthew G. Knepley   DM           dmc;
9644b4937a87SMatthew G. Knepley   PetscDS      ds;
9645b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9646b4937a87SMatthew G. Knepley   IS           cellIS;
9647b4937a87SMatthew G. Knepley   PetscFormKey key;
9648b4937a87SMatthew G. Knepley   PetscInt     depth;
9649b4937a87SMatthew G. Knepley 
9650b4937a87SMatthew G. Knepley   PetscFunctionBegin;
96519566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
96529566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
96539566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
96549566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
96559566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
96569566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
96579566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
96589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
96599566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
96609566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
96619566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9662b4937a87SMatthew G. Knepley   key.label = NULL;
9663b4937a87SMatthew G. Knepley   key.value = 0;
9664b4937a87SMatthew G. Knepley   key.field = 0;
9665b4937a87SMatthew G. Knepley   key.part  = 0;
96669566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
96679566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
96689566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
96699566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
96709566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
96719566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
96729566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
96739566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
96743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9675b4937a87SMatthew G. Knepley }
9676b4937a87SMatthew G. Knepley 
9677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9678d71ae5a4SJacob Faibussowitsch {
9679bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9680bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9681bd041c0cSMatthew G. Knepley   void        *ctx;
9682bd041c0cSMatthew G. Knepley   DM           cdm;
9683bd041c0cSMatthew G. Knepley   PetscBool    regular;
9684bd041c0cSMatthew G. Knepley 
9685bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
96863e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
96873e9753d6SMatthew G. Knepley     DM            dmc;
96883e9753d6SMatthew G. Knepley     PetscDS       ds;
9689b4937a87SMatthew G. Knepley     PetscWeakForm wf;
96903e9753d6SMatthew G. Knepley     Vec           u;
96913e9753d6SMatthew G. Knepley     IS            cellIS;
969206ad1575SMatthew G. Knepley     PetscFormKey  key;
96933e9753d6SMatthew G. Knepley     PetscInt      depth;
96943e9753d6SMatthew G. Knepley 
96959566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
96969566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
96979566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
96989566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
96999566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
97009566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
97019566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
97028d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
97039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
97049566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
97059566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
97066528b96dSMatthew G. Knepley     key.label = NULL;
97076528b96dSMatthew G. Knepley     key.value = 0;
97086528b96dSMatthew G. Knepley     key.field = 0;
970906ad1575SMatthew G. Knepley     key.part  = 0;
97109566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
97119566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
97128d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
97139566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
97143e9753d6SMatthew G. Knepley   } else {
97159566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
97169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
97179566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
97189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9719bd041c0cSMatthew G. Knepley 
97209566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
97219566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
97229566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
97239566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9724bd041c0cSMatthew G. Knepley 
97259566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
97269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
97279566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
97289566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
97293e9753d6SMatthew G. Knepley   }
97309566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
97313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9732bd041c0cSMatthew G. Knepley }
9733bd041c0cSMatthew G. Knepley 
97340aef6b92SMatthew G. Knepley /*@
97350aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
97360aef6b92SMatthew G. Knepley 
97370aef6b92SMatthew G. Knepley   Input Parameter:
9738a1cb98faSBarry Smith . dm - The `DMPLEX` object
97390aef6b92SMatthew G. Knepley 
97400aef6b92SMatthew G. Knepley   Output Parameter:
97410aef6b92SMatthew G. Knepley . regular - The flag
97420aef6b92SMatthew G. Knepley 
97430aef6b92SMatthew G. Knepley   Level: intermediate
97440aef6b92SMatthew G. Knepley 
97451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
97460aef6b92SMatthew G. Knepley @*/
9747d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
9748d71ae5a4SJacob Faibussowitsch {
97490aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97500aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9751dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
97520aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
97533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97540aef6b92SMatthew G. Knepley }
97550aef6b92SMatthew G. Knepley 
97560aef6b92SMatthew G. Knepley /*@
97570aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
97580aef6b92SMatthew G. Knepley 
97590aef6b92SMatthew G. Knepley   Input Parameters:
9760a1cb98faSBarry Smith + dm - The `DMPLEX` object
97610aef6b92SMatthew G. Knepley - regular - The flag
97620aef6b92SMatthew G. Knepley 
97630aef6b92SMatthew G. Knepley   Level: intermediate
97640aef6b92SMatthew G. Knepley 
97651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
97660aef6b92SMatthew G. Knepley @*/
9767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
9768d71ae5a4SJacob Faibussowitsch {
97690aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97700aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97710aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
97723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97730aef6b92SMatthew G. Knepley }
97740aef6b92SMatthew G. Knepley 
9775a68b90caSToby Isaac /*@
9776f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9777a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
9778a68b90caSToby Isaac 
9779a1cb98faSBarry Smith   Not Collective
9780a68b90caSToby Isaac 
9781f899ff85SJose E. Roman   Input Parameter:
9782a1cb98faSBarry Smith . dm - The `DMPLEX` object
9783a68b90caSToby Isaac 
9784a68b90caSToby Isaac   Output Parameters:
978520f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
978620f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection`
9787a68b90caSToby Isaac 
9788a68b90caSToby Isaac   Level: intermediate
9789a68b90caSToby Isaac 
97901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
9791a68b90caSToby Isaac @*/
9792d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9793d71ae5a4SJacob Faibussowitsch {
9794a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9795a68b90caSToby Isaac 
9796a68b90caSToby Isaac   PetscFunctionBegin;
9797a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97989566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9799a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9800a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
98013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9802a68b90caSToby Isaac }
9803a68b90caSToby Isaac 
9804a68b90caSToby Isaac /*@
9805f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9806f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9807a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9808a68b90caSToby Isaac 
980920f4b53cSBarry Smith   Collective
9810a68b90caSToby Isaac 
9811a68b90caSToby Isaac   Input Parameters:
9812a1cb98faSBarry Smith + dm - The `DMPLEX` object
9813a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
9814a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9815a1cb98faSBarry Smith - anchorIS - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9816a68b90caSToby Isaac 
9817a68b90caSToby Isaac   Level: intermediate
9818a68b90caSToby Isaac 
9819a1cb98faSBarry Smith   Notes:
9820a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
9821a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
9822a1cb98faSBarry Smith 
982320f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
9824a1cb98faSBarry Smith 
98251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9826a68b90caSToby Isaac @*/
9827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9828d71ae5a4SJacob Faibussowitsch {
9829a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
9830e228b242SToby Isaac   PetscMPIInt result;
9831a68b90caSToby Isaac 
9832a68b90caSToby Isaac   PetscFunctionBegin;
9833a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9834e228b242SToby Isaac   if (anchorSection) {
9835e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
98369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
98371dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
9838e228b242SToby Isaac   }
9839e228b242SToby Isaac   if (anchorIS) {
9840e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
98419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
98421dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
9843e228b242SToby Isaac   }
9844a68b90caSToby Isaac 
98459566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
98469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9847a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9848a68b90caSToby Isaac 
98499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
98509566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9851a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9852a68b90caSToby Isaac 
9853cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9854a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
9855a68b90caSToby Isaac     const PetscInt *anchors;
9856a68b90caSToby Isaac 
98579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
98589566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
98599566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
9860a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9861a68b90caSToby Isaac       PetscInt p;
9862a68b90caSToby Isaac 
9863a68b90caSToby Isaac       p = anchors[a];
9864a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9865a68b90caSToby Isaac         PetscInt dof;
9866a68b90caSToby Isaac 
98679566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9868a68b90caSToby Isaac         if (dof) {
98699566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
987063a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
9871a68b90caSToby Isaac         }
9872a68b90caSToby Isaac       }
9873a68b90caSToby Isaac     }
98749566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
9875a68b90caSToby Isaac   }
9876f7c74593SToby Isaac   /* reset the generic constraints */
98779566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
98783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9879a68b90caSToby Isaac }
9880a68b90caSToby Isaac 
9881d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9882d71ae5a4SJacob Faibussowitsch {
9883f7c74593SToby Isaac   PetscSection anchorSection;
98846995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9885a68b90caSToby Isaac 
9886a68b90caSToby Isaac   PetscFunctionBegin;
9887a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
98899566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
98909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
98916995de1eSToby Isaac   if (numFields) {
9892719ab38cSToby Isaac     PetscInt f;
98939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
9894719ab38cSToby Isaac 
9895719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9896719ab38cSToby Isaac       PetscInt numComp;
9897719ab38cSToby Isaac 
98989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
98999566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
9900719ab38cSToby Isaac     }
99016995de1eSToby Isaac   }
99029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
99039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
99046995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
99056995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
99066995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
99079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
9908a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
99099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9910a68b90caSToby Isaac     if (dof) {
99119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
99129566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
9913a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
99149566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
99159566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
9916a68b90caSToby Isaac       }
9917a68b90caSToby Isaac     }
9918a68b90caSToby Isaac   }
99199566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
99209566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
99213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9922a68b90caSToby Isaac }
9923a68b90caSToby Isaac 
9924d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9925d71ae5a4SJacob Faibussowitsch {
9926f7c74593SToby Isaac   PetscSection    aSec;
9927ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
99280ac89760SToby Isaac   const PetscInt *anchors;
99290ac89760SToby Isaac   PetscInt        numFields, f;
993066ad2231SToby Isaac   IS              aIS;
9931e19f7ee6SMark Adams   MatType         mtype;
9932e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
99330ac89760SToby Isaac 
99340ac89760SToby Isaac   PetscFunctionBegin;
99350ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
99379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
99389566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
99399566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
99409566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
99419566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
99429566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
99439566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
9944e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9945e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9946e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
99479566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
99489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
99499566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
99506995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
99519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
99529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
99539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
99540ac89760SToby Isaac   i[0] = 0;
99559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
99560ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9957f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9958f19733c5SToby Isaac 
99599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
9960f19733c5SToby Isaac     if (!rDof) continue;
99619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99620ac89760SToby Isaac     if (numFields) {
99630ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99640ac89760SToby Isaac         annz = 0;
9965f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9966f19733c5SToby Isaac           a = anchors[rOff + r];
9967ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
99689566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
99690ac89760SToby Isaac           annz += aDof;
99700ac89760SToby Isaac         }
99719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
9973ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99740ac89760SToby Isaac       }
99752f7452b8SBarry Smith     } else {
99760ac89760SToby Isaac       annz = 0;
99779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99780ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9979ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9980ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
99819566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
99820ac89760SToby Isaac         annz += aDof;
99830ac89760SToby Isaac       }
99849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
9986ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99870ac89760SToby Isaac     }
99880ac89760SToby Isaac   }
99890ac89760SToby Isaac   nnz = i[m];
99909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
99910ac89760SToby Isaac   offset = 0;
99920ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
99930ac89760SToby Isaac     if (numFields) {
99940ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99960ac89760SToby Isaac         for (q = 0; q < dof; q++) {
99970ac89760SToby Isaac           PetscInt rDof, rOff, r;
99989566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
99999566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
100000ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
100010ac89760SToby Isaac             PetscInt s;
100020ac89760SToby Isaac 
100030ac89760SToby Isaac             a = anchors[rOff + r];
10004ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
100059566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
100069566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10007ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
100080ac89760SToby Isaac           }
100090ac89760SToby Isaac         }
100100ac89760SToby Isaac       }
100112f7452b8SBarry Smith     } else {
100129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
100130ac89760SToby Isaac       for (q = 0; q < dof; q++) {
100140ac89760SToby Isaac         PetscInt rDof, rOff, r;
100159566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
100169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
100170ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
100180ac89760SToby Isaac           PetscInt s;
100190ac89760SToby Isaac 
100200ac89760SToby Isaac           a = anchors[rOff + r];
10021ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
100229566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
100239566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10024ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
100250ac89760SToby Isaac         }
100260ac89760SToby Isaac       }
100270ac89760SToby Isaac     }
100280ac89760SToby Isaac   }
100299566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
100309566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
100319566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
100329566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
100333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
100340ac89760SToby Isaac }
100350ac89760SToby Isaac 
10036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10037d71ae5a4SJacob Faibussowitsch {
10038f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10039f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1004066ad2231SToby Isaac   Mat          cMat;
1004166ad2231SToby Isaac 
1004266ad2231SToby Isaac   PetscFunctionBegin;
1004366ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1004566ad2231SToby Isaac   if (anchorSection) {
1004644a7f3ddSMatthew G. Knepley     PetscInt Nf;
10047e228b242SToby Isaac 
100489566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
100499566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
100509566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
100519566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
100529566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
100539566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
100549566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
100559566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1005666ad2231SToby Isaac   }
100573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1005866ad2231SToby Isaac }
10059a93c429eSMatthew G. Knepley 
10060d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10061d71ae5a4SJacob Faibussowitsch {
10062a93c429eSMatthew G. Knepley   IS           subis;
10063a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10064a93c429eSMatthew G. Knepley 
10065a93c429eSMatthew G. Knepley   PetscFunctionBegin;
100669566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1006728b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1006828b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10069a93c429eSMatthew G. Knepley   /* Create subdomain */
100709566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10071a93c429eSMatthew G. Knepley   /* Create submodel */
100729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
100739566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
100749566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
100759566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
100769566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10077a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10078a93c429eSMatthew G. Knepley   if (is) {
10079a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10080a93c429eSMatthew G. Knepley     IS              spIS;
10081a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10082a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10083a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10084a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10085a93c429eSMatthew G. Knepley 
100869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
100879566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
100889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
100899566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
100909566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
100919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10092a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10093a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10094a93c429eSMatthew G. Knepley 
100959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10096a93c429eSMatthew G. Knepley       if (gdof > 0) {
10097a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10098a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10099a93c429eSMatthew G. Knepley 
101009566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
101019566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10102a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10103a93c429eSMatthew G. Knepley         }
10104a93c429eSMatthew G. Knepley         subSize += pSubSize;
10105a93c429eSMatthew G. Knepley         if (pSubSize) {
10106a93c429eSMatthew G. Knepley           if (bs < 0) {
10107a93c429eSMatthew G. Knepley             bs = pSubSize;
10108a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10109a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10110a93c429eSMatthew G. Knepley             bs = 1;
10111a93c429eSMatthew G. Knepley           }
10112a93c429eSMatthew G. Knepley         }
10113a93c429eSMatthew G. Knepley       }
10114a93c429eSMatthew G. Knepley     }
10115a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
101169371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
101179371c9d4SSatish Balay     bsLocal[1] = bs;
101189566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
101199371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
101209371c9d4SSatish Balay       bs = 1;
101219371c9d4SSatish Balay     } else {
101229371c9d4SSatish Balay       bs = bsMinMax[0];
101239371c9d4SSatish Balay     }
101249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10125a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10126a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10127a93c429eSMatthew G. Knepley 
101289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10129a93c429eSMatthew G. Knepley       if (gdof > 0) {
10130a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10131a93c429eSMatthew G. Knepley 
101329566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10133a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10134a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10135a93c429eSMatthew G. Knepley 
10136a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10137a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
101389566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
101399566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10140a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10141a93c429eSMatthew G. Knepley           }
101429566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
101439566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10144ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10145a93c429eSMatthew G. Knepley         }
10146a93c429eSMatthew G. Knepley       }
10147a93c429eSMatthew G. Knepley     }
101489566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
101499566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10150a93c429eSMatthew G. Knepley     if (bs > 1) {
10151a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10152a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10153a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10154a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
101559371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
101569371c9d4SSatish Balay             set = 0;
101579371c9d4SSatish Balay             break;
101589371c9d4SSatish Balay           }
10159a93c429eSMatthew G. Knepley         }
10160a93c429eSMatthew G. Knepley       }
101619566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10162a93c429eSMatthew G. Knepley     }
10163a93c429eSMatthew G. Knepley     /* Attach nullspace */
10164a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10165a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10166a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10167a93c429eSMatthew G. Knepley     }
10168a93c429eSMatthew G. Knepley     if (f < Nf) {
10169a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
101709566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
101716823f3c5SBlaise Bourdin 
101729566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
101739566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10174a93c429eSMatthew G. Knepley     }
10175a93c429eSMatthew G. Knepley   }
101763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10177a93c429eSMatthew G. Knepley }
10178c0f0dcc3SMatthew G. Knepley 
10179c0f0dcc3SMatthew G. Knepley /*@
10180c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10181c0f0dcc3SMatthew G. Knepley 
10182a1cb98faSBarry Smith   Input Parameters:
10183a1cb98faSBarry Smith + dm - The `DM`
10184a1cb98faSBarry Smith - dummy - unused argument
10185a1cb98faSBarry Smith 
10186a1cb98faSBarry Smith   Options Database Key:
10187a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10188c0f0dcc3SMatthew G. Knepley 
10189c0f0dcc3SMatthew G. Knepley   Level: developer
10190c0f0dcc3SMatthew G. Knepley 
101911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10192c0f0dcc3SMatthew G. Knepley @*/
10193d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10194d71ae5a4SJacob Faibussowitsch {
10195e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
10196c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
10197c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
10198c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
10199c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
10200c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
10201c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
10202c0f0dcc3SMatthew G. Knepley   const char        *name;
10203e5ed2c37SJose E. Roman #endif
10204c0f0dcc3SMatthew G. Knepley 
10205c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
10206c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10207c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
102089566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
102099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
102109566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
102119566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
102129566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
102139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
102149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
10215c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart) * Nf * eventInfo.count;
10216c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops / eventInfo.time;
10217c0f0dcc3SMatthew G. Knepley   cellRate = N / eventInfo.time;
1021863a3b9bcSJacob 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)));
10219c0f0dcc3SMatthew G. Knepley #else
10220c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
10221c0f0dcc3SMatthew G. Knepley #endif
102223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10223c0f0dcc3SMatthew G. Knepley }
10224