xref: /petsc/src/dm/impls/plex/plex.c (revision d1c358715b6fe09f9db569701363392faf513a57)
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));
25369f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
25379566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
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;
2758552f7358SJed Brown 
2759552f7358SJed Brown   PetscFunctionBegin;
2760552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
27629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
27633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2764552f7358SJed Brown }
2765552f7358SJed Brown 
2766552f7358SJed Brown /*@
2767eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2768552f7358SJed Brown 
2769a1cb98faSBarry Smith   Not Collective
2770552f7358SJed Brown 
2771552f7358SJed Brown   Input Parameters:
2772a1cb98faSBarry Smith + mesh - The `DMPLEX`
2773a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
2774552f7358SJed Brown 
2775552f7358SJed Brown   Output Parameter:
277620f4b53cSBarry Smith . size - The cone size for point `p`
2777552f7358SJed Brown 
2778552f7358SJed Brown   Level: beginner
2779552f7358SJed Brown 
27801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2781552f7358SJed Brown @*/
2782d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2783d71ae5a4SJacob Faibussowitsch {
2784552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2785552f7358SJed Brown 
2786552f7358SJed Brown   PetscFunctionBegin;
2787552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2788dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
27899f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
27909f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
27913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2792552f7358SJed Brown }
2793552f7358SJed Brown 
2794552f7358SJed Brown /*@
2795eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2796552f7358SJed Brown 
2797a1cb98faSBarry Smith   Not Collective
2798552f7358SJed Brown 
2799552f7358SJed Brown   Input Parameters:
2800a1cb98faSBarry Smith + mesh - The `DMPLEX`
2801a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
280220f4b53cSBarry Smith - size - The cone size for point `p`
2803552f7358SJed Brown 
2804552f7358SJed Brown   Level: beginner
2805552f7358SJed Brown 
2806a1cb98faSBarry Smith   Note:
2807a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
2808a1cb98faSBarry Smith 
28091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2810552f7358SJed Brown @*/
2811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2812d71ae5a4SJacob Faibussowitsch {
2813552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2814552f7358SJed Brown 
2815552f7358SJed Brown   PetscFunctionBegin;
2816552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28179f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
28189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
28193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2820552f7358SJed Brown }
2821552f7358SJed Brown 
2822552f7358SJed Brown /*@C
2823eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2824552f7358SJed Brown 
2825a1cb98faSBarry Smith   Not Collective
2826552f7358SJed Brown 
2827552f7358SJed Brown   Input Parameters:
2828a1cb98faSBarry Smith + dm - The `DMPLEX`
2829a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
2830552f7358SJed Brown 
2831552f7358SJed Brown   Output Parameter:
283220f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
2833552f7358SJed Brown 
2834552f7358SJed Brown   Level: beginner
2835552f7358SJed Brown 
2836a1cb98faSBarry Smith   Fortran Note:
2837a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
2838a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
28393813dfbdSMatthew G Knepley 
28401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
2841552f7358SJed Brown @*/
2842d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2843d71ae5a4SJacob Faibussowitsch {
2844552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2845552f7358SJed Brown   PetscInt off;
2846552f7358SJed Brown 
2847552f7358SJed Brown   PetscFunctionBegin;
2848552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2849552f7358SJed Brown   PetscValidPointer(cone, 3);
28509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2851552f7358SJed Brown   *cone = &mesh->cones[off];
28523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2853552f7358SJed Brown }
2854552f7358SJed Brown 
28550ce7577fSVaclav Hapla /*@C
28560ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
28570ce7577fSVaclav Hapla 
2858a1cb98faSBarry Smith   Not Collective
28590ce7577fSVaclav Hapla 
28600ce7577fSVaclav Hapla   Input Parameters:
2861a1cb98faSBarry Smith + dm - The `DMPLEX`
2862a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
28630ce7577fSVaclav Hapla 
2864d8d19677SJose E. Roman   Output Parameters:
286520f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
286620f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p`
28670ce7577fSVaclav Hapla 
28680ce7577fSVaclav Hapla   Level: intermediate
28690ce7577fSVaclav Hapla 
28701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
28710ce7577fSVaclav Hapla @*/
2872d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
2873d71ae5a4SJacob Faibussowitsch {
28740ce7577fSVaclav Hapla   PetscSection cs, newcs;
28750ce7577fSVaclav Hapla   PetscInt    *cones;
28760ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
28770ce7577fSVaclav Hapla   PetscInt     n;
28780ce7577fSVaclav Hapla 
28790ce7577fSVaclav Hapla   PetscFunctionBegin;
28809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28829566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
28830ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28840ce7577fSVaclav Hapla   if (pCones) {
28859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28869566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28870ce7577fSVaclav Hapla   }
28883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28890ce7577fSVaclav Hapla }
28900ce7577fSVaclav Hapla 
2891af9eab45SVaclav Hapla /*@
2892af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2893d4636a37SVaclav Hapla 
2894a1cb98faSBarry Smith   Not Collective
2895d4636a37SVaclav Hapla 
2896d4636a37SVaclav Hapla   Input Parameters:
2897a1cb98faSBarry Smith + dm - The `DMPLEX`
2898a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2899d4636a37SVaclav Hapla 
2900d4636a37SVaclav Hapla   Output Parameter:
2901af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2902d4636a37SVaclav Hapla 
2903d4636a37SVaclav Hapla   Level: advanced
2904d4636a37SVaclav Hapla 
2905af9eab45SVaclav Hapla   Notes:
290620f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
2907af9eab45SVaclav Hapla 
2908a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
2909a1cb98faSBarry Smith 
29101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
2911a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
2912d4636a37SVaclav Hapla @*/
2913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2914d71ae5a4SJacob Faibussowitsch {
2915af9eab45SVaclav Hapla   IS      *expandedPointsAll;
2916af9eab45SVaclav Hapla   PetscInt depth;
2917d4636a37SVaclav Hapla 
2918d4636a37SVaclav Hapla   PetscFunctionBegin;
2919af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2920af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2921af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
29229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2923af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
29249566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
29259566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
29263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2927af9eab45SVaclav Hapla }
2928af9eab45SVaclav Hapla 
2929af9eab45SVaclav Hapla /*@
2930af9eab45SVaclav 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).
2931af9eab45SVaclav Hapla 
2932a1cb98faSBarry Smith   Not Collective
2933af9eab45SVaclav Hapla 
2934af9eab45SVaclav Hapla   Input Parameters:
2935a1cb98faSBarry Smith + dm - The `DMPLEX`
2936a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2937af9eab45SVaclav Hapla 
2938d8d19677SJose E. Roman   Output Parameters:
2939a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
2940af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2941af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2942af9eab45SVaclav Hapla 
2943af9eab45SVaclav Hapla   Level: advanced
2944af9eab45SVaclav Hapla 
2945af9eab45SVaclav Hapla   Notes:
2946a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
2947af9eab45SVaclav Hapla 
294820f4b53cSBarry 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.
2949af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2950af9eab45SVaclav Hapla 
295120f4b53cSBarry 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:
295220f4b53cSBarry Smith   (1) DAG points in expandedPoints[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
295320f4b53cSBarry Smith   (2) DAG points in expandedPoints[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
2954af9eab45SVaclav Hapla 
29551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
2956a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
2957af9eab45SVaclav Hapla @*/
2958d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2959d71ae5a4SJacob Faibussowitsch {
2960af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
2961af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
2962af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
2963af9eab45SVaclav Hapla   IS             *expandedPoints_;
2964af9eab45SVaclav Hapla   PetscSection   *sections_;
2965af9eab45SVaclav Hapla 
2966af9eab45SVaclav Hapla   PetscFunctionBegin;
2967af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2968af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2969af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2970af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2971af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
29729566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29739566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29769566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2977af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
2978af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
29799566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2981af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
2983af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29849566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29859566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2986af9eab45SVaclav Hapla       } else {
29879566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2988af9eab45SVaclav Hapla       }
2989af9eab45SVaclav Hapla     }
29909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29929566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2993af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2996af9eab45SVaclav Hapla       if (cn > 1) {
29979566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
29989566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
2999af9eab45SVaclav Hapla       } else {
3000af9eab45SVaclav Hapla         newarr[co] = arr[i];
3001af9eab45SVaclav Hapla       }
3002af9eab45SVaclav Hapla     }
30039566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3004af9eab45SVaclav Hapla     arr = newarr;
3005af9eab45SVaclav Hapla     n   = newn;
3006af9eab45SVaclav Hapla   }
30079566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3008af9eab45SVaclav Hapla   *depth = depth_;
3009af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3010af9eab45SVaclav Hapla   else {
30119566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
30129566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3013af9eab45SVaclav Hapla   }
3014af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3015af9eab45SVaclav Hapla   else {
30169566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
30179566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3018af9eab45SVaclav Hapla   }
30193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3020af9eab45SVaclav Hapla }
3021af9eab45SVaclav Hapla 
3022af9eab45SVaclav Hapla /*@
3023a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3024af9eab45SVaclav Hapla 
3025a1cb98faSBarry Smith   Not Collective
3026af9eab45SVaclav Hapla 
3027af9eab45SVaclav Hapla   Input Parameters:
3028a1cb98faSBarry Smith + dm - The `DMPLEX`
3029a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3030af9eab45SVaclav Hapla 
3031d8d19677SJose E. Roman   Output Parameters:
3032a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3033af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3034af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
3035af9eab45SVaclav Hapla 
3036af9eab45SVaclav Hapla   Level: advanced
3037af9eab45SVaclav Hapla 
3038a1cb98faSBarry Smith   Note:
3039a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3040af9eab45SVaclav Hapla 
30411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3042a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3043af9eab45SVaclav Hapla @*/
3044d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3045d71ae5a4SJacob Faibussowitsch {
3046af9eab45SVaclav Hapla   PetscInt d, depth_;
3047af9eab45SVaclav Hapla 
3048af9eab45SVaclav Hapla   PetscFunctionBegin;
30499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
30501dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3051af9eab45SVaclav Hapla   if (depth) *depth = 0;
3052af9eab45SVaclav Hapla   if (expandedPoints) {
30539566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
30549566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3055af9eab45SVaclav Hapla   }
3056af9eab45SVaclav Hapla   if (sections) {
30579566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
30589566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3059af9eab45SVaclav Hapla   }
30603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3061d4636a37SVaclav Hapla }
3062d4636a37SVaclav Hapla 
3063552f7358SJed Brown /*@
306492371b87SBarry 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
3065552f7358SJed Brown 
3066a1cb98faSBarry Smith   Not Collective
3067552f7358SJed Brown 
3068552f7358SJed Brown   Input Parameters:
3069a1cb98faSBarry Smith + mesh - The `DMPLEX`
3070a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
307120f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3072552f7358SJed Brown 
3073552f7358SJed Brown   Level: beginner
3074552f7358SJed Brown 
3075a1cb98faSBarry Smith   Note:
3076a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3077a1cb98faSBarry Smith 
30781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3079552f7358SJed Brown @*/
3080d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3081d71ae5a4SJacob Faibussowitsch {
3082552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3083552f7358SJed Brown   PetscInt pStart, pEnd;
3084552f7358SJed Brown   PetscInt dof, off, c;
3085552f7358SJed Brown 
3086552f7358SJed Brown   PetscFunctionBegin;
3087552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3090dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
309263a3b9bcSJacob 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);
3093552f7358SJed Brown   for (c = 0; c < dof; ++c) {
309463a3b9bcSJacob 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);
3095552f7358SJed Brown     mesh->cones[off + c] = cone[c];
3096552f7358SJed Brown   }
30973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3098552f7358SJed Brown }
3099552f7358SJed Brown 
3100552f7358SJed Brown /*@C
3101eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3102552f7358SJed Brown 
3103a1cb98faSBarry Smith   Not Collective
3104552f7358SJed Brown 
3105552f7358SJed Brown   Input Parameters:
3106a1cb98faSBarry Smith + mesh - The `DMPLEX`
3107a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3108552f7358SJed Brown 
3109552f7358SJed Brown   Output Parameter:
311020f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3111b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3112552f7358SJed Brown 
3113552f7358SJed Brown   Level: beginner
3114552f7358SJed Brown 
3115a1cb98faSBarry Smith   Note:
3116b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3117b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3118a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3119b5a892a1SMatthew G. Knepley   with the identity.
3120b5a892a1SMatthew G. Knepley 
3121a1cb98faSBarry Smith   Fortran Note:
3122a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3123a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
31243813dfbdSMatthew G Knepley 
31251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3126552f7358SJed Brown @*/
3127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3128d71ae5a4SJacob Faibussowitsch {
3129552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3130552f7358SJed Brown   PetscInt off;
3131552f7358SJed Brown 
3132552f7358SJed Brown   PetscFunctionBegin;
3133552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
313476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3135552f7358SJed Brown     PetscInt dof;
31369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3137552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3138552f7358SJed Brown   }
31399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
31400d644c17SKarl Rupp 
3141552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
31423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3143552f7358SJed Brown }
3144552f7358SJed Brown 
3145552f7358SJed Brown /*@
3146eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3147552f7358SJed Brown 
3148a1cb98faSBarry Smith   Not Collective
3149552f7358SJed Brown 
3150552f7358SJed Brown   Input Parameters:
3151a1cb98faSBarry Smith + mesh - The `DMPLEX`
3152a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
3153b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3154b5a892a1SMatthew G. Knepley 
3155552f7358SJed Brown   Level: beginner
3156552f7358SJed Brown 
3157a1cb98faSBarry Smith   Notes:
3158a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3159a1cb98faSBarry Smith 
3160a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3161a1cb98faSBarry Smith 
31621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3163552f7358SJed Brown @*/
3164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3165d71ae5a4SJacob Faibussowitsch {
3166552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3167552f7358SJed Brown   PetscInt pStart, pEnd;
3168552f7358SJed Brown   PetscInt dof, off, c;
3169552f7358SJed Brown 
3170552f7358SJed Brown   PetscFunctionBegin;
3171552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3174dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
31759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
317663a3b9bcSJacob 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);
3177552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3178552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3179552f7358SJed Brown 
31809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
31811dca8a05SBarry 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);
3182552f7358SJed Brown     mesh->coneOrientations[off + c] = o;
3183552f7358SJed Brown   }
31843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3185552f7358SJed Brown }
3186552f7358SJed Brown 
31877cd05799SMatthew G. Knepley /*@
3188eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31897cd05799SMatthew G. Knepley 
3190a1cb98faSBarry Smith   Not Collective
31917cd05799SMatthew G. Knepley 
31927cd05799SMatthew G. Knepley   Input Parameters:
3193a1cb98faSBarry Smith + mesh - The `DMPLEX`
3194a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
31957cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31967cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31977cd05799SMatthew G. Knepley 
31987cd05799SMatthew G. Knepley   Level: beginner
31997cd05799SMatthew G. Knepley 
32001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32017cd05799SMatthew G. Knepley @*/
3202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3203d71ae5a4SJacob Faibussowitsch {
3204552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3205552f7358SJed Brown   PetscInt pStart, pEnd;
3206552f7358SJed Brown   PetscInt dof, off;
3207552f7358SJed Brown 
3208552f7358SJed Brown   PetscFunctionBegin;
3209552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
321163a3b9bcSJacob 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);
321263a3b9bcSJacob 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);
32139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
321563a3b9bcSJacob 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);
3216552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
32173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3218552f7358SJed Brown }
3219552f7358SJed Brown 
32207cd05799SMatthew G. Knepley /*@
3221eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
32227cd05799SMatthew G. Knepley 
3223a1cb98faSBarry Smith   Not Collective
32247cd05799SMatthew G. Knepley 
32257cd05799SMatthew G. Knepley   Input Parameters:
3226a1cb98faSBarry Smith + mesh - The `DMPLEX`
3227a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
32287cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
32297cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
32307cd05799SMatthew G. Knepley 
32317cd05799SMatthew G. Knepley   Level: beginner
32327cd05799SMatthew G. Knepley 
3233a1cb98faSBarry Smith   Note:
3234a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3235b5a892a1SMatthew G. Knepley 
32361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32377cd05799SMatthew G. Knepley @*/
3238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3239d71ae5a4SJacob Faibussowitsch {
324077c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
324177c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
324277c88f5bSMatthew G Knepley   PetscInt dof, off;
324377c88f5bSMatthew G Knepley 
324477c88f5bSMatthew G Knepley   PetscFunctionBegin;
324577c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
324763a3b9bcSJacob 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);
32489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
325063a3b9bcSJacob 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);
325177c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
32523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
325377c88f5bSMatthew G Knepley }
325477c88f5bSMatthew G Knepley 
32559f4ada15SMatthew G. Knepley /*@C
32569f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
32579f4ada15SMatthew G. Knepley 
32589f4ada15SMatthew G. Knepley   Not collective
32599f4ada15SMatthew G. Knepley 
32609f4ada15SMatthew G. Knepley   Input Parameters:
32619f4ada15SMatthew G. Knepley + dm - The DMPlex
32629f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
32639f4ada15SMatthew G. Knepley 
32649f4ada15SMatthew G. Knepley   Output Parameters:
326520f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
326620f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
32679f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
32689f4ada15SMatthew G. Knepley 
32699f4ada15SMatthew G. Knepley   Level: beginner
32709f4ada15SMatthew G. Knepley 
32719f4ada15SMatthew G. Knepley   Notes:
32729f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
32739f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
327420f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
32759f4ada15SMatthew G. Knepley   with the identity.
32769f4ada15SMatthew G. Knepley 
32779f4ada15SMatthew G. Knepley   Fortran Notes:
327820f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
327920f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
32809f4ada15SMatthew G. Knepley 
32811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
32829f4ada15SMatthew G. Knepley @*/
32839f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
32849f4ada15SMatthew G. Knepley {
32859f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
32869f4ada15SMatthew G. Knepley 
32879f4ada15SMatthew G. Knepley   PetscFunctionBegin;
32889f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32899f4ada15SMatthew G. Knepley   if (mesh->tr) {
32909f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
32919f4ada15SMatthew G. Knepley   } else {
32929f4ada15SMatthew G. Knepley     PetscInt off;
32939f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
32949f4ada15SMatthew G. Knepley       PetscInt dof;
32959f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32969f4ada15SMatthew G. Knepley       if (dof) {
32979f4ada15SMatthew G. Knepley         if (cone) PetscValidPointer(cone, 3);
32989f4ada15SMatthew G. Knepley         if (ornt) PetscValidPointer(ornt, 4);
32999f4ada15SMatthew G. Knepley       }
33009f4ada15SMatthew G. Knepley     }
33019f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33029f4ada15SMatthew G. Knepley     if (cone) *cone = &mesh->cones[off];
33039f4ada15SMatthew G. Knepley     if (ornt) *ornt = &mesh->coneOrientations[off];
33049f4ada15SMatthew G. Knepley   }
33053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33069f4ada15SMatthew G. Knepley }
33079f4ada15SMatthew G. Knepley 
33089f4ada15SMatthew G. Knepley /*@C
33099f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
33109f4ada15SMatthew G. Knepley 
331120f4b53cSBarry Smith   Not Collective
33129f4ada15SMatthew G. Knepley 
33139f4ada15SMatthew G. Knepley   Input Parameters:
33149f4ada15SMatthew G. Knepley + dm - The DMPlex
331520f4b53cSBarry Smith . p  - The point, which must lie in the chart set with `DMPlexSetChart()`
33169f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
331720f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
33189f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
33199f4ada15SMatthew G. Knepley 
33209f4ada15SMatthew G. Knepley   Level: beginner
33219f4ada15SMatthew G. Knepley 
33229f4ada15SMatthew G. Knepley   Notes:
33239f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
33249f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
332520f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
33269f4ada15SMatthew G. Knepley   with the identity.
33279f4ada15SMatthew G. Knepley 
332820f4b53cSBarry Smith   Fortran Note:
332920f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
333020f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
33319f4ada15SMatthew G. Knepley 
33321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
33339f4ada15SMatthew G. Knepley @*/
33349f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
33359f4ada15SMatthew G. Knepley {
33369f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
33379f4ada15SMatthew G. Knepley 
33389f4ada15SMatthew G. Knepley   PetscFunctionBegin;
33399f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33409f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
33413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33429f4ada15SMatthew G. Knepley }
33439f4ada15SMatthew G. Knepley 
3344552f7358SJed Brown /*@
3345eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3346552f7358SJed Brown 
3347a1cb98faSBarry Smith   Not Collective
3348552f7358SJed Brown 
3349552f7358SJed Brown   Input Parameters:
3350a1cb98faSBarry Smith + mesh - The `DMPLEX`
3351a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3352552f7358SJed Brown 
3353552f7358SJed Brown   Output Parameter:
335420f4b53cSBarry Smith . size - The support size for point `p`
3355552f7358SJed Brown 
3356552f7358SJed Brown   Level: beginner
3357552f7358SJed Brown 
33581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3359552f7358SJed Brown @*/
3360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3361d71ae5a4SJacob Faibussowitsch {
3362552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3363552f7358SJed Brown 
3364552f7358SJed Brown   PetscFunctionBegin;
3365552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3366dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
33679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
33683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3369552f7358SJed Brown }
3370552f7358SJed Brown 
3371552f7358SJed Brown /*@
3372eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3373552f7358SJed Brown 
3374a1cb98faSBarry Smith   Not Collective
3375552f7358SJed Brown 
3376552f7358SJed Brown   Input Parameters:
3377a1cb98faSBarry Smith + mesh - The `DMPLEX`
3378a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
337920f4b53cSBarry Smith - size - The support size for point `p`
3380552f7358SJed Brown 
3381a1cb98faSBarry Smith   Level: beginner
3382552f7358SJed Brown 
3383552f7358SJed Brown   Note:
338420f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3385552f7358SJed Brown 
33861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3387552f7358SJed Brown @*/
3388d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3389d71ae5a4SJacob Faibussowitsch {
3390552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3391552f7358SJed Brown 
3392552f7358SJed Brown   PetscFunctionBegin;
3393552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
33953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3396552f7358SJed Brown }
3397552f7358SJed Brown 
3398552f7358SJed Brown /*@C
3399eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3400552f7358SJed Brown 
3401a1cb98faSBarry Smith   Not Collective
3402552f7358SJed Brown 
3403552f7358SJed Brown   Input Parameters:
3404a1cb98faSBarry Smith + mesh - The `DMPLEX`
3405a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3406552f7358SJed Brown 
3407552f7358SJed Brown   Output Parameter:
340820f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3409552f7358SJed Brown 
3410552f7358SJed Brown   Level: beginner
3411552f7358SJed Brown 
3412a1cb98faSBarry Smith   Fortran Note:
3413a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3414a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
34153813dfbdSMatthew G Knepley 
34161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3417552f7358SJed Brown @*/
3418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3419d71ae5a4SJacob Faibussowitsch {
3420552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3421552f7358SJed Brown   PetscInt off;
3422552f7358SJed Brown 
3423552f7358SJed Brown   PetscFunctionBegin;
3424552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3425552f7358SJed Brown   PetscValidPointer(support, 3);
34269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3427552f7358SJed Brown   *support = &mesh->supports[off];
34283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3429552f7358SJed Brown }
3430552f7358SJed Brown 
3431552f7358SJed Brown /*@
343292371b87SBarry 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
3433552f7358SJed Brown 
3434a1cb98faSBarry Smith   Not Collective
3435552f7358SJed Brown 
3436552f7358SJed Brown   Input Parameters:
3437a1cb98faSBarry Smith + mesh - The `DMPLEX`
3438a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
343920f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3440552f7358SJed Brown 
3441552f7358SJed Brown   Level: beginner
3442552f7358SJed Brown 
3443a1cb98faSBarry Smith   Note:
3444a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3445a1cb98faSBarry Smith 
34461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3447552f7358SJed Brown @*/
3448d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3449d71ae5a4SJacob Faibussowitsch {
3450552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3451552f7358SJed Brown   PetscInt pStart, pEnd;
3452552f7358SJed Brown   PetscInt dof, off, c;
3453552f7358SJed Brown 
3454552f7358SJed Brown   PetscFunctionBegin;
3455552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
34579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3458dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
34599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
346063a3b9bcSJacob 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);
3461552f7358SJed Brown   for (c = 0; c < dof; ++c) {
346263a3b9bcSJacob 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);
3463552f7358SJed Brown     mesh->supports[off + c] = support[c];
3464552f7358SJed Brown   }
34653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3466552f7358SJed Brown }
3467552f7358SJed Brown 
34687cd05799SMatthew G. Knepley /*@
3469eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
34707cd05799SMatthew G. Knepley 
3471a1cb98faSBarry Smith   Not Collective
34727cd05799SMatthew G. Knepley 
34737cd05799SMatthew G. Knepley   Input Parameters:
3474a1cb98faSBarry Smith + mesh - The `DMPLEX`
3475a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
34767cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
34777cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
34787cd05799SMatthew G. Knepley 
34797cd05799SMatthew G. Knepley   Level: beginner
34807cd05799SMatthew G. Knepley 
34811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34827cd05799SMatthew G. Knepley @*/
3483d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3484d71ae5a4SJacob Faibussowitsch {
3485552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3486552f7358SJed Brown   PetscInt pStart, pEnd;
3487552f7358SJed Brown   PetscInt dof, off;
3488552f7358SJed Brown 
3489552f7358SJed Brown   PetscFunctionBegin;
3490552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
34929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
34939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
349463a3b9bcSJacob 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);
349563a3b9bcSJacob 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);
349663a3b9bcSJacob 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);
3497552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
34983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3499552f7358SJed Brown }
3500552f7358SJed Brown 
3501b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3502d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3503d71ae5a4SJacob Faibussowitsch {
3504b5a892a1SMatthew G. Knepley   switch (ct) {
3505b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3506b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3507b5a892a1SMatthew G. Knepley     break;
3508b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3509b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3510b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3511b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3512b5a892a1SMatthew G. Knepley     break;
3513b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3514b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3515b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3516b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3517b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3518b5a892a1SMatthew G. Knepley     break;
3519d71ae5a4SJacob Faibussowitsch   default:
3520d71ae5a4SJacob Faibussowitsch     return o;
3521b5a892a1SMatthew G. Knepley   }
3522b5a892a1SMatthew G. Knepley   return o;
3523b5a892a1SMatthew G. Knepley }
3524b5a892a1SMatthew G. Knepley 
3525b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3526d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3527d71ae5a4SJacob Faibussowitsch {
3528b5a892a1SMatthew G. Knepley   switch (ct) {
3529b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3530b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3531b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3532b5a892a1SMatthew G. Knepley     break;
3533b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3534b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3535b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3536b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3537b5a892a1SMatthew G. Knepley     break;
3538b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3539b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3540b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3541b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3542b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3543b5a892a1SMatthew G. Knepley     break;
3544d71ae5a4SJacob Faibussowitsch   default:
3545d71ae5a4SJacob Faibussowitsch     return o;
3546b5a892a1SMatthew G. Knepley   }
3547b5a892a1SMatthew G. Knepley   return o;
3548b5a892a1SMatthew G. Knepley }
3549b5a892a1SMatthew G. Knepley 
3550b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3551d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3552d71ae5a4SJacob Faibussowitsch {
3553b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3554b5a892a1SMatthew G. Knepley 
3555b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
35569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3557b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3558b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3559b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3560b5a892a1SMatthew G. Knepley 
35619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
35629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
35639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3564b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3565b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3566b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3567b5a892a1SMatthew G. Knepley 
35689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3569b5a892a1SMatthew G. Knepley       switch (ct) {
3570b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
35719566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35729566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3573b5a892a1SMatthew G. Knepley         break;
3574b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
35759566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
35769566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35779566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3578b5a892a1SMatthew G. Knepley         break;
3579b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
35809566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
35819566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35829566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
35839566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3584b5a892a1SMatthew G. Knepley         break;
3585d71ae5a4SJacob Faibussowitsch       default:
3586d71ae5a4SJacob Faibussowitsch         break;
3587b5a892a1SMatthew G. Knepley       }
3588b5a892a1SMatthew G. Knepley     }
3589b5a892a1SMatthew G. Knepley   }
35903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3591b5a892a1SMatthew G. Knepley }
3592b5a892a1SMatthew G. Knepley 
3593d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3594d71ae5a4SJacob Faibussowitsch {
3595b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3596b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3597b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3598b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3599b5a892a1SMatthew G. Knepley 
3600b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3601b5a892a1SMatthew G. Knepley   if (ornt) {
36029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3603b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3604b5a892a1SMatthew G. Knepley   }
3605b5a892a1SMatthew G. Knepley   if (*points) {
3606b5a892a1SMatthew G. Knepley     closure = *points;
3607b5a892a1SMatthew G. Knepley   } else {
3608b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
36099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
36109566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3611b5a892a1SMatthew G. Knepley   }
3612b5a892a1SMatthew G. Knepley   if (useCone) {
36139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
36149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
36159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3616b5a892a1SMatthew G. Knepley   } else {
36179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
36189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3619b5a892a1SMatthew G. Knepley   }
3620b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3621b5a892a1SMatthew G. Knepley     closure[off++] = p;
3622b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3623b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3624b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3625b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3626b5a892a1SMatthew G. Knepley     }
3627b5a892a1SMatthew G. Knepley   } else {
36285f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3629b5a892a1SMatthew G. Knepley 
3630b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3631b5a892a1SMatthew G. Knepley     closure[off++] = p;
3632b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3633b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3634b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3635b5a892a1SMatthew G. Knepley 
36369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3637b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3638b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3639b5a892a1SMatthew G. Knepley     }
3640b5a892a1SMatthew G. Knepley   }
3641b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3642b5a892a1SMatthew G. Knepley   if (points) *points = closure;
36433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3644b5a892a1SMatthew G. Knepley }
3645b5a892a1SMatthew G. Knepley 
3646d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3647d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3648d71ae5a4SJacob Faibussowitsch {
3649b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3650b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3651b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3652b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3653b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3654b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3655b5a892a1SMatthew G. Knepley 
3656b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
36579566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
36589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
36599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
36609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
36619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3662b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3663b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3664b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
36659371c9d4SSatish Balay   if (*points) {
36669371c9d4SSatish Balay     pts = *points;
36679371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3668b5a892a1SMatthew G. Knepley   c        = 0;
3669b5a892a1SMatthew G. Knepley   pts[c++] = point;
3670b5a892a1SMatthew G. Knepley   pts[c++] = o;
36719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
36729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
36739371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
36749371c9d4SSatish Balay     pts[c++] = closure[cl];
36759371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
36769371c9d4SSatish Balay   }
36779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
36789371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
36799371c9d4SSatish Balay     pts[c++] = closure[cl];
36809371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
36819371c9d4SSatish Balay   }
36829566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3683b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
36849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3685b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3686b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3687b5a892a1SMatthew G. Knepley   }
3688b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3689b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3690b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3691b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3692b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3693b5a892a1SMatthew G. Knepley 
36949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3695b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
36969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
36979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
36989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3699b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3700b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3701b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3702b5a892a1SMatthew G. Knepley 
37039371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
37049371c9d4SSatish Balay           if (pts[i] == cp) break;
3705b5a892a1SMatthew G. Knepley         if (i == c) {
37069566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3707b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3708b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3709b5a892a1SMatthew G. Knepley         }
3710b5a892a1SMatthew G. Knepley       }
3711b5a892a1SMatthew G. Knepley     }
3712b5a892a1SMatthew G. Knepley   }
3713b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3714b5a892a1SMatthew G. Knepley   *points    = pts;
37153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3716b5a892a1SMatthew G. Knepley }
3717b5a892a1SMatthew G. Knepley 
3718d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3719d71ae5a4SJacob Faibussowitsch {
3720b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3721b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3722b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3723b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3724b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3725b5a892a1SMatthew G. Knepley 
3726b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
37279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3728b5a892a1SMatthew G. Knepley   if (depth == 1) {
37299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
37303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3731b5a892a1SMatthew G. Knepley   }
37329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3733b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3734b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
37359566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
37363ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3737b5a892a1SMatthew G. Knepley   }
37389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3739b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3740b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3741b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
37429566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
37439371c9d4SSatish Balay   if (*points) {
37449371c9d4SSatish Balay     closure = *points;
37459371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3746b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3747b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3748b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3749b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3750b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3751b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3752b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3753b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3754b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3755b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
3756b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3757b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3758b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3759b5a892a1SMatthew G. Knepley 
3760b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3761b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2;
376263a3b9bcSJacob 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);
3763b5a892a1SMatthew G. Knepley     }
3764b5a892a1SMatthew G. Knepley     if (useCone) {
37659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
37669566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
37679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3768b5a892a1SMatthew G. Knepley     } else {
37699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
37709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3771b5a892a1SMatthew G. Knepley       tmpO = NULL;
3772b5a892a1SMatthew G. Knepley     }
3773b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3774b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
3775b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
3776b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
37779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3778b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3779b5a892a1SMatthew G. Knepley       PetscInt       c;
3780b5a892a1SMatthew G. Knepley 
3781b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3782b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3783b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3784b5a892a1SMatthew G. Knepley       }
3785b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3786b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3787b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3788b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3789b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3790b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3791b5a892a1SMatthew G. Knepley       }
3792b5a892a1SMatthew G. Knepley     }
3793b5a892a1SMatthew G. Knepley   }
37949566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
3795b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
3796b5a892a1SMatthew G. Knepley   if (points) *points = closure;
37973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3798b5a892a1SMatthew G. Knepley }
3799b5a892a1SMatthew G. Knepley 
3800552f7358SJed Brown /*@C
3801eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3802552f7358SJed Brown 
3803a1cb98faSBarry Smith   Not Collective
3804552f7358SJed Brown 
3805552f7358SJed Brown   Input Parameters:
3806a1cb98faSBarry Smith + dm      - The `DMPLEX`
3807b5a892a1SMatthew G. Knepley . p       - The mesh point
3808a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
3809552f7358SJed Brown 
38106b867d5aSJose E. Roman   Input/Output Parameter:
38116b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
381220f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
38136b867d5aSJose E. Roman 
38146b867d5aSJose E. Roman   Output Parameter:
381520f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
3816552f7358SJed Brown 
3817a1cb98faSBarry Smith   Level: beginner
3818a1cb98faSBarry Smith 
3819552f7358SJed Brown   Note:
382020f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
3821552f7358SJed Brown 
38229f22da38SBarry Smith   Fortran Note:
382320f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
38243813dfbdSMatthew G Knepley 
38251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3826552f7358SJed Brown @*/
3827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3828d71ae5a4SJacob Faibussowitsch {
3829b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3830552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3831b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3832b5a892a1SMatthew G. Knepley   if (points) PetscValidPointer(points, 5);
38339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
38343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38359bf0dad6SMatthew G. Knepley }
38369bf0dad6SMatthew G. Knepley 
3837552f7358SJed Brown /*@C
3838eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3839552f7358SJed Brown 
3840a1cb98faSBarry Smith   Not Collective
3841552f7358SJed Brown 
3842552f7358SJed Brown   Input Parameters:
3843a1cb98faSBarry Smith + dm        - The `DMPLEX`
3844b5a892a1SMatthew G. Knepley . p         - The mesh point
3845a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
384620f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
3847b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3848552f7358SJed Brown 
3849a1cb98faSBarry Smith   Level: beginner
3850a1cb98faSBarry Smith 
3851552f7358SJed Brown   Note:
385220f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
3853552f7358SJed Brown 
38541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3855552f7358SJed Brown @*/
3856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3857d71ae5a4SJacob Faibussowitsch {
3858b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3859552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38604ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
38619566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
38623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3863552f7358SJed Brown }
3864552f7358SJed Brown 
3865552f7358SJed Brown /*@
3866eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3867552f7358SJed Brown 
3868a1cb98faSBarry Smith   Not Collective
3869552f7358SJed Brown 
3870552f7358SJed Brown   Input Parameter:
3871a1cb98faSBarry Smith . mesh - The `DMPLEX`
3872552f7358SJed Brown 
3873552f7358SJed Brown   Output Parameters:
3874552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3875552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3876552f7358SJed Brown 
3877552f7358SJed Brown   Level: beginner
3878552f7358SJed Brown 
38791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3880552f7358SJed Brown @*/
3881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3882d71ae5a4SJacob Faibussowitsch {
3883552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3884552f7358SJed Brown 
3885552f7358SJed Brown   PetscFunctionBegin;
3886552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38871baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
38881baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
38893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3890552f7358SJed Brown }
3891552f7358SJed Brown 
3892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
3893d71ae5a4SJacob Faibussowitsch {
3894552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
38956302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
3896552f7358SJed Brown 
3897552f7358SJed Brown   PetscFunctionBegin;
3898552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
39009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
39019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
39029566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
39036302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
39046302a7fbSVaclav Hapla   if (maxSupportSize) {
39059566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
39069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
39079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
3908552f7358SJed Brown   }
39093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3910552f7358SJed Brown }
3911552f7358SJed Brown 
3912d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3913d71ae5a4SJacob Faibussowitsch {
3914552f7358SJed Brown   PetscFunctionBegin;
39159566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
39169566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3917ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
3918736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
391995602cf2SAlexis Marboeuf     PetscSF sfNatural;
3920f94b4a02SBlaise Bourdin 
39213dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
39229566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
392395602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
3924c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3925f94b4a02SBlaise Bourdin   }
39263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3927552f7358SJed Brown }
3928552f7358SJed Brown 
3929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
3930d71ae5a4SJacob Faibussowitsch {
39313dcd263cSBlaise Bourdin   PetscInt i = 0;
39322adcc780SMatthew G. Knepley 
39332adcc780SMatthew G. Knepley   PetscFunctionBegin;
39349566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
39359566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3936c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
39373dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
39383dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
393995602cf2SAlexis Marboeuf       PetscSF sfNatural;
39403dcd263cSBlaise Bourdin 
39413dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
39429566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
3943c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
394495602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
3945c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
39463dcd263cSBlaise Bourdin       break;
39473dcd263cSBlaise Bourdin     }
39483dcd263cSBlaise Bourdin   }
39493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39502adcc780SMatthew G. Knepley }
39512adcc780SMatthew G. Knepley 
3952552f7358SJed Brown /*@
3953eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3954552f7358SJed Brown 
3955a1cb98faSBarry Smith   Not Collective
3956552f7358SJed Brown 
3957552f7358SJed Brown   Input Parameter:
3958a1cb98faSBarry Smith . mesh - The `DMPLEX`
3959552f7358SJed Brown 
3960552f7358SJed Brown   Level: beginner
3961552f7358SJed Brown 
3962a1cb98faSBarry Smith   Note:
3963a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
3964a1cb98faSBarry Smith 
39651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3966552f7358SJed Brown @*/
3967d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
3968d71ae5a4SJacob Faibussowitsch {
3969552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
3970552f7358SJed Brown   PetscInt *offsets;
3971552f7358SJed Brown   PetscInt  supportSize;
3972552f7358SJed Brown   PetscInt  pStart, pEnd, p;
3973552f7358SJed Brown 
3974552f7358SJed Brown   PetscFunctionBegin;
3975552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
397628b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
39779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
3978552f7358SJed Brown   /* Calculate support sizes */
39799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3980552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3981552f7358SJed Brown     PetscInt dof, off, c;
3982552f7358SJed Brown 
39839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
39849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
398548a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3986552f7358SJed Brown   }
39879566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3988552f7358SJed Brown   /* Calculate supports */
39899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
39909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
39919566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3992552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3993552f7358SJed Brown     PetscInt dof, off, c;
3994552f7358SJed Brown 
39959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
39969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3997552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
3998552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3999552f7358SJed Brown       PetscInt       offS;
4000552f7358SJed Brown 
40019566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
40020d644c17SKarl Rupp 
4003552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4004552f7358SJed Brown       ++offsets[q];
4005552f7358SJed Brown     }
4006552f7358SJed Brown   }
40079566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
40089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
40093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4010552f7358SJed Brown }
4011552f7358SJed Brown 
4012d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4013d71ae5a4SJacob Faibussowitsch {
4014277ea44aSLisandro Dalcin   IS stratumIS;
4015277ea44aSLisandro Dalcin 
4016277ea44aSLisandro Dalcin   PetscFunctionBegin;
40173ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
401876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4019277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4020277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
40219566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4022277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
40239566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
40249371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
40259371c9d4SSatish Balay         overlap = PETSC_TRUE;
40269371c9d4SSatish Balay         break;
40279371c9d4SSatish Balay       }
4028277ea44aSLisandro Dalcin     }
402963a3b9bcSJacob 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);
4030277ea44aSLisandro Dalcin   }
40319566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
40329566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
40339566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
40343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4035277ea44aSLisandro Dalcin }
4036277ea44aSLisandro Dalcin 
4037552f7358SJed Brown /*@
4038a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
40396dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
4040552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
4041552f7358SJed Brown   the DAG.
4042552f7358SJed Brown 
404320f4b53cSBarry Smith   Collective
4044552f7358SJed Brown 
4045552f7358SJed Brown   Input Parameter:
4046a1cb98faSBarry Smith . mesh - The `DMPLEX`
4047552f7358SJed Brown 
4048a1cb98faSBarry Smith   Level: beginner
4049552f7358SJed Brown 
4050552f7358SJed Brown   Notes:
4051a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4052b1bb481bSMatthew 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
4053a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4054a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4055a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4056552f7358SJed Brown 
4057b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4058b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4059b1bb481bSMatthew 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
4060b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4061a1cb98faSBarry Smith .vb
4062a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4063a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4064a1cb98faSBarry Smith .ve
4065a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4066a1cb98faSBarry Smith .vb
4067a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4068a1cb98faSBarry Smith    depth 1 = {e0, c0}
4069a1cb98faSBarry Smith .ve
4070b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4071b1bb481bSMatthew Knepley 
4072a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4073552f7358SJed Brown 
40741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4075552f7358SJed Brown @*/
4076d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4077d71ae5a4SJacob Faibussowitsch {
4078df0420ecSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4079aa50250dSMatthew G. Knepley   DMLabel  label;
4080552f7358SJed Brown   PetscInt pStart, pEnd, p;
4081552f7358SJed Brown   PetscInt numRoots = 0, numLeaves = 0;
4082552f7358SJed Brown 
4083552f7358SJed Brown   PetscFunctionBegin;
4084552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4086277ea44aSLisandro Dalcin 
4087277ea44aSLisandro Dalcin   /* Create depth label */
40889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
40899566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
40909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4091277ea44aSLisandro Dalcin 
4092277ea44aSLisandro Dalcin   {
4093552f7358SJed Brown     /* Initialize roots and count leaves */
4094277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4095277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4096552f7358SJed Brown     PetscInt coneSize, supportSize;
4097552f7358SJed Brown 
4098277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
40999566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4101552f7358SJed Brown       if (!coneSize && supportSize) {
4102277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4103277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4104552f7358SJed Brown         ++numRoots;
4105552f7358SJed Brown       } else if (!supportSize && coneSize) {
4106552f7358SJed Brown         ++numLeaves;
4107552f7358SJed Brown       } else if (!supportSize && !coneSize) {
4108552f7358SJed Brown         /* Isolated points */
4109277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4110277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4111552f7358SJed Brown       }
4112552f7358SJed Brown     }
41139566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4114277ea44aSLisandro Dalcin   }
4115277ea44aSLisandro Dalcin 
4116552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
4117277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4118277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4119552f7358SJed Brown     PetscInt coneSize, supportSize;
4120552f7358SJed Brown 
4121277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
41229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41239566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4124552f7358SJed Brown       if (!supportSize && coneSize) {
4125277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4126277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4127552f7358SJed Brown       }
4128552f7358SJed Brown     }
41299566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4130552f7358SJed Brown   } else {
4131277ea44aSLisandro Dalcin     PetscInt level = 0;
4132277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
4133552f7358SJed Brown 
41349566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4135277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4136277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4137277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
413874ef644bSMatthew G. Knepley 
4139277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
414074ef644bSMatthew G. Knepley         const PetscInt *support;
414174ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
414274ef644bSMatthew G. Knepley 
41439566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
41449566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
414574ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4146277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4147277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4148552f7358SJed Brown         }
4149552f7358SJed Brown       }
41509566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
41519566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
41529566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
415374ef644bSMatthew G. Knepley     }
415474ef644bSMatthew G. Knepley   }
4155bf4602e4SToby Isaac   { /* just in case there is an empty process */
4156bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4157bf4602e4SToby Isaac 
41589566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4159712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
416048a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4161bf4602e4SToby Isaac   }
41629566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
41639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
41643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4165552f7358SJed Brown }
4166552f7358SJed Brown 
4167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4168d71ae5a4SJacob Faibussowitsch {
4169412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4170412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4171ba2698f1SMatthew G. Knepley 
4172412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
41739566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
41749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
41759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4176ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4177ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4178ba2698f1SMatthew G. Knepley     switch (pdepth) {
4179d71ae5a4SJacob Faibussowitsch     case 0:
4180d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4181d71ae5a4SJacob Faibussowitsch       break;
4182ba2698f1SMatthew G. Knepley     case 1:
4183ba2698f1SMatthew G. Knepley       switch (coneSize) {
4184d71ae5a4SJacob Faibussowitsch       case 2:
4185d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4186d71ae5a4SJacob Faibussowitsch         break;
4187d71ae5a4SJacob Faibussowitsch       case 3:
4188d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4189d71ae5a4SJacob Faibussowitsch         break;
4190ba2698f1SMatthew G. Knepley       case 4:
4191ba2698f1SMatthew G. Knepley         switch (dim) {
4192d71ae5a4SJacob Faibussowitsch         case 2:
4193d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4194d71ae5a4SJacob Faibussowitsch           break;
4195d71ae5a4SJacob Faibussowitsch         case 3:
4196d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4197d71ae5a4SJacob Faibussowitsch           break;
4198d71ae5a4SJacob Faibussowitsch         default:
4199d71ae5a4SJacob Faibussowitsch           break;
4200ba2698f1SMatthew G. Knepley         }
4201ba2698f1SMatthew G. Knepley         break;
4202d71ae5a4SJacob Faibussowitsch       case 5:
4203d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4204d71ae5a4SJacob Faibussowitsch         break;
4205d71ae5a4SJacob Faibussowitsch       case 6:
4206d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4207d71ae5a4SJacob Faibussowitsch         break;
4208d71ae5a4SJacob Faibussowitsch       case 8:
4209d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4210d71ae5a4SJacob Faibussowitsch         break;
4211d71ae5a4SJacob Faibussowitsch       default:
4212d71ae5a4SJacob Faibussowitsch         break;
4213ba2698f1SMatthew G. Knepley       }
4214ba2698f1SMatthew G. Knepley     }
4215ba2698f1SMatthew G. Knepley   } else {
4216ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4217ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4218ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4219ba2698f1SMatthew G. Knepley       switch (dim) {
4220ba2698f1SMatthew G. Knepley       case 1:
4221ba2698f1SMatthew G. Knepley         switch (coneSize) {
4222d71ae5a4SJacob Faibussowitsch         case 2:
4223d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4224d71ae5a4SJacob Faibussowitsch           break;
4225d71ae5a4SJacob Faibussowitsch         default:
4226d71ae5a4SJacob Faibussowitsch           break;
4227ba2698f1SMatthew G. Knepley         }
4228ba2698f1SMatthew G. Knepley         break;
4229ba2698f1SMatthew G. Knepley       case 2:
4230ba2698f1SMatthew G. Knepley         switch (coneSize) {
4231d71ae5a4SJacob Faibussowitsch         case 3:
4232d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4233d71ae5a4SJacob Faibussowitsch           break;
4234d71ae5a4SJacob Faibussowitsch         case 4:
4235d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4236d71ae5a4SJacob Faibussowitsch           break;
4237d71ae5a4SJacob Faibussowitsch         default:
4238d71ae5a4SJacob Faibussowitsch           break;
4239ba2698f1SMatthew G. Knepley         }
4240ba2698f1SMatthew G. Knepley         break;
4241ba2698f1SMatthew G. Knepley       case 3:
4242ba2698f1SMatthew G. Knepley         switch (coneSize) {
4243d71ae5a4SJacob Faibussowitsch         case 4:
4244d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4245d71ae5a4SJacob Faibussowitsch           break;
42469371c9d4SSatish Balay         case 5: {
4247da9060c4SMatthew G. Knepley           const PetscInt *cone;
4248da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4249da9060c4SMatthew G. Knepley 
42509566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
42519566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4252da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4253d71ae5a4SJacob Faibussowitsch           case 3:
4254d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4255d71ae5a4SJacob Faibussowitsch             break;
4256d71ae5a4SJacob Faibussowitsch           case 4:
4257d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4258d71ae5a4SJacob Faibussowitsch             break;
4259da9060c4SMatthew G. Knepley           }
42609371c9d4SSatish Balay         } break;
4261d71ae5a4SJacob Faibussowitsch         case 6:
4262d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4263d71ae5a4SJacob Faibussowitsch           break;
4264d71ae5a4SJacob Faibussowitsch         default:
4265d71ae5a4SJacob Faibussowitsch           break;
4266ba2698f1SMatthew G. Knepley         }
4267ba2698f1SMatthew G. Knepley         break;
4268d71ae5a4SJacob Faibussowitsch       default:
4269d71ae5a4SJacob Faibussowitsch         break;
4270ba2698f1SMatthew G. Knepley       }
4271ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4272ba2698f1SMatthew G. Knepley       switch (coneSize) {
4273d71ae5a4SJacob Faibussowitsch       case 2:
4274d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4275d71ae5a4SJacob Faibussowitsch         break;
4276d71ae5a4SJacob Faibussowitsch       case 3:
4277d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4278d71ae5a4SJacob Faibussowitsch         break;
4279d71ae5a4SJacob Faibussowitsch       case 4:
4280d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4281d71ae5a4SJacob Faibussowitsch         break;
4282d71ae5a4SJacob Faibussowitsch       default:
4283d71ae5a4SJacob Faibussowitsch         break;
4284ba2698f1SMatthew G. Knepley       }
4285ba2698f1SMatthew G. Knepley     }
4286ba2698f1SMatthew G. Knepley   }
4287412e9a14SMatthew G. Knepley   *pt = ct;
42883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4289ba2698f1SMatthew G. Knepley }
4290412e9a14SMatthew G. Knepley 
4291412e9a14SMatthew G. Knepley /*@
4292412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4293412e9a14SMatthew G. Knepley 
429420f4b53cSBarry Smith   Collective
4295412e9a14SMatthew G. Knepley 
4296412e9a14SMatthew G. Knepley   Input Parameter:
4297a1cb98faSBarry Smith . mesh - The `DMPLEX`
4298412e9a14SMatthew G. Knepley 
4299412e9a14SMatthew G. Knepley   Level: developer
4300412e9a14SMatthew G. Knepley 
4301a1cb98faSBarry Smith   Note:
4302a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4303a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4304a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4305412e9a14SMatthew G. Knepley 
4306a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4307a1cb98faSBarry Smith 
43081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4309412e9a14SMatthew G. Knepley @*/
4310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4311d71ae5a4SJacob Faibussowitsch {
4312412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4313412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4314412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4315412e9a14SMatthew G. Knepley 
4316412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4317412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4318412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
43199566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
43209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
43219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4322412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4323327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4324412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4325412e9a14SMatthew G. Knepley 
43269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
43279566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
432863a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
43299566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4330412e9a14SMatthew G. Knepley   }
43319566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
43329566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
43333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4334ba2698f1SMatthew G. Knepley }
4335ba2698f1SMatthew G. Knepley 
4336552f7358SJed Brown /*@C
4337552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4338552f7358SJed Brown 
4339552f7358SJed Brown   Not Collective
4340552f7358SJed Brown 
4341552f7358SJed Brown   Input Parameters:
4342a1cb98faSBarry Smith + dm - The `DMPLEX` object
4343552f7358SJed Brown . numPoints - The number of input points for the join
4344552f7358SJed Brown - points - The input points
4345552f7358SJed Brown 
4346552f7358SJed Brown   Output Parameters:
4347552f7358SJed Brown + numCoveredPoints - The number of points in the join
4348552f7358SJed Brown - coveredPoints - The points in the join
4349552f7358SJed Brown 
4350552f7358SJed Brown   Level: intermediate
4351552f7358SJed Brown 
4352a1cb98faSBarry Smith   Note:
4353a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4354552f7358SJed Brown 
4355a1cb98faSBarry Smith   Fortran Note:
435620f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
43573813dfbdSMatthew G Knepley 
43581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4359552f7358SJed Brown @*/
4360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4361d71ae5a4SJacob Faibussowitsch {
4362552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4363552f7358SJed Brown   PetscInt *join[2];
4364552f7358SJed Brown   PetscInt  joinSize, i = 0;
4365552f7358SJed Brown   PetscInt  dof, off, p, c, m;
43666302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4367552f7358SJed Brown 
4368552f7358SJed Brown   PetscFunctionBegin;
4369552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
437048bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
437148bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
437248bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
43736302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
43746302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
43756302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4376552f7358SJed Brown   /* Copy in support of first point */
43779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
43789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4379ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4380552f7358SJed Brown   /* Check each successive support */
4381552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4382552f7358SJed Brown     PetscInt newJoinSize = 0;
4383552f7358SJed Brown 
43849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
43859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4386552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4387552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4388552f7358SJed Brown 
4389552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4390552f7358SJed Brown         if (point == join[i][m]) {
4391552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4392552f7358SJed Brown           break;
4393552f7358SJed Brown         }
4394552f7358SJed Brown       }
4395552f7358SJed Brown     }
4396552f7358SJed Brown     joinSize = newJoinSize;
4397552f7358SJed Brown     i        = 1 - i;
4398552f7358SJed Brown   }
4399552f7358SJed Brown   *numCoveredPoints = joinSize;
4400552f7358SJed Brown   *coveredPoints    = join[i];
44016302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
44023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4403552f7358SJed Brown }
4404552f7358SJed Brown 
4405552f7358SJed Brown /*@C
4406552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4407552f7358SJed Brown 
4408552f7358SJed Brown   Not Collective
4409552f7358SJed Brown 
4410552f7358SJed Brown   Input Parameters:
4411a1cb98faSBarry Smith + dm - The `DMPLEX` object
4412552f7358SJed Brown . numPoints - The number of input points for the join
4413552f7358SJed Brown - points - The input points
4414552f7358SJed Brown 
4415552f7358SJed Brown   Output Parameters:
4416552f7358SJed Brown + numCoveredPoints - The number of points in the join
4417552f7358SJed Brown - coveredPoints - The points in the join
4418552f7358SJed Brown 
4419552f7358SJed Brown   Level: intermediate
4420552f7358SJed Brown 
4421a1cb98faSBarry Smith   Fortran Note:
442220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4423a1cb98faSBarry Smith 
44241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4425552f7358SJed Brown @*/
4426d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4427d71ae5a4SJacob Faibussowitsch {
4428552f7358SJed Brown   PetscFunctionBegin;
4429552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4430d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4431d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4432d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
44339566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4434d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
44353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4436552f7358SJed Brown }
4437552f7358SJed Brown 
4438552f7358SJed Brown /*@C
4439552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4440552f7358SJed Brown 
4441552f7358SJed Brown   Not Collective
4442552f7358SJed Brown 
4443552f7358SJed Brown   Input Parameters:
4444a1cb98faSBarry Smith + dm - The `DMPLEX` object
4445552f7358SJed Brown . numPoints - The number of input points for the join
4446552f7358SJed Brown - points - The input points
4447552f7358SJed Brown 
4448552f7358SJed Brown   Output Parameters:
4449552f7358SJed Brown + numCoveredPoints - The number of points in the join
4450552f7358SJed Brown - coveredPoints - The points in the join
4451552f7358SJed Brown 
4452552f7358SJed Brown   Level: intermediate
4453552f7358SJed Brown 
4454a1cb98faSBarry Smith   Fortran Note:
445520f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4456a1cb98faSBarry Smith 
44571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4458552f7358SJed Brown @*/
4459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4460d71ae5a4SJacob Faibussowitsch {
4461552f7358SJed Brown   PetscInt *offsets, **closures;
4462552f7358SJed Brown   PetscInt *join[2];
4463552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
446424c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4465552f7358SJed Brown 
4466552f7358SJed Brown   PetscFunctionBegin;
4467552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
446848bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
446948bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
447048bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4471552f7358SJed Brown 
44729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
44739566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
44749566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
44756302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
447624c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
44779566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
44789566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4479552f7358SJed Brown 
4480552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4481552f7358SJed Brown     PetscInt closureSize;
4482552f7358SJed Brown 
44839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
44840d644c17SKarl Rupp 
4485552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4486552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4487552f7358SJed Brown       PetscInt pStart, pEnd, i;
4488552f7358SJed Brown 
44899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4490552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4491552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4492552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4493552f7358SJed Brown           break;
4494552f7358SJed Brown         }
4495552f7358SJed Brown       }
4496552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4497552f7358SJed Brown     }
449863a3b9bcSJacob 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);
4499552f7358SJed Brown   }
4500552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4501552f7358SJed Brown     PetscInt dof;
4502552f7358SJed Brown 
4503552f7358SJed Brown     /* Copy in support of first point */
4504552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4505ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4506552f7358SJed Brown     /* Check each successive cone */
4507552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4508552f7358SJed Brown       PetscInt newJoinSize = 0;
4509552f7358SJed Brown 
4510552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4511552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4512552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4513552f7358SJed Brown 
4514552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4515552f7358SJed Brown           if (point == join[i][m]) {
4516552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4517552f7358SJed Brown             break;
4518552f7358SJed Brown           }
4519552f7358SJed Brown         }
4520552f7358SJed Brown       }
4521552f7358SJed Brown       joinSize = newJoinSize;
4522552f7358SJed Brown       i        = 1 - i;
4523552f7358SJed Brown     }
4524552f7358SJed Brown     if (joinSize) break;
4525552f7358SJed Brown   }
4526552f7358SJed Brown   *numCoveredPoints = joinSize;
4527552f7358SJed Brown   *coveredPoints    = join[i];
452848a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
45299566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45309566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
45316302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
45323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4533552f7358SJed Brown }
4534552f7358SJed Brown 
4535552f7358SJed Brown /*@C
4536552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4537552f7358SJed Brown 
4538552f7358SJed Brown   Not Collective
4539552f7358SJed Brown 
4540552f7358SJed Brown   Input Parameters:
4541a1cb98faSBarry Smith + dm - The `DMPLEX` object
4542552f7358SJed Brown . numPoints - The number of input points for the meet
4543552f7358SJed Brown - points - The input points
4544552f7358SJed Brown 
4545552f7358SJed Brown   Output Parameters:
4546552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4547552f7358SJed Brown - coveredPoints - The points in the meet
4548552f7358SJed Brown 
4549552f7358SJed Brown   Level: intermediate
4550552f7358SJed Brown 
4551a1cb98faSBarry Smith   Note:
4552a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4553552f7358SJed Brown 
45543813dfbdSMatthew G Knepley   Fortran Notes:
455520f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
45563813dfbdSMatthew G Knepley 
45571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4558552f7358SJed Brown @*/
4559d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4560d71ae5a4SJacob Faibussowitsch {
4561552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4562552f7358SJed Brown   PetscInt *meet[2];
4563552f7358SJed Brown   PetscInt  meetSize, i = 0;
4564552f7358SJed Brown   PetscInt  dof, off, p, c, m;
45656302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4566552f7358SJed Brown 
4567552f7358SJed Brown   PetscFunctionBegin;
4568552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4569dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4570dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4571064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
45726302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
45736302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
45746302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4575552f7358SJed Brown   /* Copy in cone of first point */
45769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
45779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4578ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4579552f7358SJed Brown   /* Check each successive cone */
4580552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4581552f7358SJed Brown     PetscInt newMeetSize = 0;
4582552f7358SJed Brown 
45839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
45849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4585552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4586552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4587552f7358SJed Brown 
4588552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4589552f7358SJed Brown         if (point == meet[i][m]) {
4590552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4591552f7358SJed Brown           break;
4592552f7358SJed Brown         }
4593552f7358SJed Brown       }
4594552f7358SJed Brown     }
4595552f7358SJed Brown     meetSize = newMeetSize;
4596552f7358SJed Brown     i        = 1 - i;
4597552f7358SJed Brown   }
4598552f7358SJed Brown   *numCoveringPoints = meetSize;
4599552f7358SJed Brown   *coveringPoints    = meet[i];
46006302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
46013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4602552f7358SJed Brown }
4603552f7358SJed Brown 
4604552f7358SJed Brown /*@C
4605552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4606552f7358SJed Brown 
4607552f7358SJed Brown   Not Collective
4608552f7358SJed Brown 
4609552f7358SJed Brown   Input Parameters:
4610a1cb98faSBarry Smith + dm - The `DMPLEX` object
4611552f7358SJed Brown . numPoints - The number of input points for the meet
4612552f7358SJed Brown - points - The input points
4613552f7358SJed Brown 
4614552f7358SJed Brown   Output Parameters:
4615552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4616552f7358SJed Brown - coveredPoints - The points in the meet
4617552f7358SJed Brown 
4618552f7358SJed Brown   Level: intermediate
4619552f7358SJed Brown 
4620a1cb98faSBarry Smith   Fortran Note:
462120f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46223813dfbdSMatthew G Knepley 
46231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4624552f7358SJed Brown @*/
4625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4626d71ae5a4SJacob Faibussowitsch {
4627552f7358SJed Brown   PetscFunctionBegin;
4628552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4629d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4630d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4631d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
46329566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4633d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
46343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4635552f7358SJed Brown }
4636552f7358SJed Brown 
4637552f7358SJed Brown /*@C
4638552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4639552f7358SJed Brown 
4640552f7358SJed Brown   Not Collective
4641552f7358SJed Brown 
4642552f7358SJed Brown   Input Parameters:
4643a1cb98faSBarry Smith + dm - The `DMPLEX` object
4644552f7358SJed Brown . numPoints - The number of input points for the meet
4645552f7358SJed Brown - points - The input points
4646552f7358SJed Brown 
4647552f7358SJed Brown   Output Parameters:
4648552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4649552f7358SJed Brown - coveredPoints - The points in the meet
4650552f7358SJed Brown 
4651552f7358SJed Brown   Level: intermediate
4652552f7358SJed Brown 
4653a1cb98faSBarry Smith   Fortran Note:
465420f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46553813dfbdSMatthew G Knepley 
46561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4657552f7358SJed Brown @*/
4658d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4659d71ae5a4SJacob Faibussowitsch {
4660552f7358SJed Brown   PetscInt *offsets, **closures;
4661552f7358SJed Brown   PetscInt *meet[2];
4662552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
466324c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4664552f7358SJed Brown 
4665552f7358SJed Brown   PetscFunctionBegin;
4666552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4667dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4668dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4669064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4670552f7358SJed Brown 
46719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
46729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
46739566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
46746302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
467524c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
46769566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
46779566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4678552f7358SJed Brown 
4679552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4680552f7358SJed Brown     PetscInt closureSize;
4681552f7358SJed Brown 
46829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
46830d644c17SKarl Rupp 
4684552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4685552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4686552f7358SJed Brown       PetscInt pStart, pEnd, i;
4687552f7358SJed Brown 
46889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4689552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4690552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4691552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4692552f7358SJed Brown           break;
4693552f7358SJed Brown         }
4694552f7358SJed Brown       }
4695552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4696552f7358SJed Brown     }
469763a3b9bcSJacob 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);
4698552f7358SJed Brown   }
4699552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4700552f7358SJed Brown     PetscInt dof;
4701552f7358SJed Brown 
4702552f7358SJed Brown     /* Copy in cone of first point */
4703552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
4704ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
4705552f7358SJed Brown     /* Check each successive cone */
4706552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4707552f7358SJed Brown       PetscInt newMeetSize = 0;
4708552f7358SJed Brown 
4709552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
4710552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4711552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
4712552f7358SJed Brown 
4713552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4714552f7358SJed Brown           if (point == meet[i][m]) {
4715552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
4716552f7358SJed Brown             break;
4717552f7358SJed Brown           }
4718552f7358SJed Brown         }
4719552f7358SJed Brown       }
4720552f7358SJed Brown       meetSize = newMeetSize;
4721552f7358SJed Brown       i        = 1 - i;
4722552f7358SJed Brown     }
4723552f7358SJed Brown     if (meetSize) break;
4724552f7358SJed Brown   }
4725552f7358SJed Brown   *numCoveredPoints = meetSize;
4726552f7358SJed Brown   *coveredPoints    = meet[i];
472748a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
47289566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
47299566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
47306302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
47313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4732552f7358SJed Brown }
4733552f7358SJed Brown 
47344e3744c5SMatthew G. Knepley /*@C
4735a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
47364e3744c5SMatthew G. Knepley 
47374e3744c5SMatthew G. Knepley   Not Collective
47384e3744c5SMatthew G. Knepley 
47394e3744c5SMatthew G. Knepley   Input Parameters:
4740a1cb98faSBarry Smith + dmA - A `DMPLEX` object
4741a1cb98faSBarry Smith - dmB - A `DMPLEX` object
47424e3744c5SMatthew G. Knepley 
47432fe279fdSBarry Smith   Output Parameter:
4744a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
47454e3744c5SMatthew G. Knepley 
47464e3744c5SMatthew G. Knepley   Level: intermediate
47474e3744c5SMatthew G. Knepley 
4748a1cb98faSBarry Smith   Note:
47493c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
47504e3744c5SMatthew G. Knepley 
47511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
47524e3744c5SMatthew G. Knepley @*/
4753d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
4754d71ae5a4SJacob Faibussowitsch {
47554e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
47564e3744c5SMatthew G. Knepley 
47574e3744c5SMatthew G. Knepley   PetscFunctionBegin;
47584e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
47594e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4760dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
47614e3744c5SMatthew G. Knepley 
47624e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
47639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
47649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
47653ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
47669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
47679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
47683ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
47694e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
47704e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
47714e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
47724e3744c5SMatthew G. Knepley 
47739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
47749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
47759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
47769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
47779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
47789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
47793ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
47804e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
47813ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
47823ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
47834e3744c5SMatthew G. Knepley     }
47849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
47859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
47869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
47879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
47883ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
47894e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
47903ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
47914e3744c5SMatthew G. Knepley     }
47924e3744c5SMatthew G. Knepley   }
47934e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
47943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47954e3744c5SMatthew G. Knepley }
47964e3744c5SMatthew G. Knepley 
47977cd05799SMatthew G. Knepley /*@C
47987cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
47997cd05799SMatthew G. Knepley 
48007cd05799SMatthew G. Knepley   Not Collective
48017cd05799SMatthew G. Knepley 
48027cd05799SMatthew G. Knepley   Input Parameters:
4803a1cb98faSBarry Smith + dm         - The `DMPLEX`
48047cd05799SMatthew G. Knepley . cellDim    - The cell dimension
48057cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
48067cd05799SMatthew G. Knepley 
48072fe279fdSBarry Smith   Output Parameter:
48087cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
48097cd05799SMatthew G. Knepley 
48107cd05799SMatthew G. Knepley   Level: developer
48117cd05799SMatthew G. Knepley 
4812a1cb98faSBarry Smith   Note:
48137cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
48147cd05799SMatthew G. Knepley 
48151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
48167cd05799SMatthew G. Knepley @*/
4817d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4818d71ae5a4SJacob Faibussowitsch {
481982f516ccSBarry Smith   MPI_Comm comm;
4820552f7358SJed Brown 
4821552f7358SJed Brown   PetscFunctionBegin;
48229566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4823dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices, 4);
4824552f7358SJed Brown   switch (cellDim) {
4825d71ae5a4SJacob Faibussowitsch   case 0:
4826d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
4827d71ae5a4SJacob Faibussowitsch     break;
4828d71ae5a4SJacob Faibussowitsch   case 1:
4829d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
4830d71ae5a4SJacob Faibussowitsch     break;
4831552f7358SJed Brown   case 2:
4832552f7358SJed Brown     switch (numCorners) {
483319436ca2SJed Brown     case 3:                 /* triangle */
483419436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4835552f7358SJed Brown       break;
483619436ca2SJed Brown     case 4:                 /* quadrilateral */
483719436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4838552f7358SJed Brown       break;
483919436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
484019436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4841552f7358SJed Brown       break;
484219436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
484319436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4844552f7358SJed Brown       break;
4845d71ae5a4SJacob Faibussowitsch     default:
4846d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4847552f7358SJed Brown     }
4848552f7358SJed Brown     break;
4849552f7358SJed Brown   case 3:
4850552f7358SJed Brown     switch (numCorners) {
485119436ca2SJed Brown     case 4:                 /* tetradehdron */
485219436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4853552f7358SJed Brown       break;
485419436ca2SJed Brown     case 6:                 /* tet cohesive cells */
485519436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4856552f7358SJed Brown       break;
485719436ca2SJed Brown     case 8:                 /* hexahedron */
485819436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4859552f7358SJed Brown       break;
486019436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
486119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4862552f7358SJed Brown       break;
486319436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
486419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4865552f7358SJed Brown       break;
486619436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
486719436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4868552f7358SJed Brown       break;
486919436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
487019436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4871552f7358SJed Brown       break;
487219436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
487319436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4874552f7358SJed Brown       break;
4875d71ae5a4SJacob Faibussowitsch     default:
4876d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4877552f7358SJed Brown     }
4878552f7358SJed Brown     break;
4879d71ae5a4SJacob Faibussowitsch   default:
4880d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4881552f7358SJed Brown   }
48823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4883552f7358SJed Brown }
4884552f7358SJed Brown 
4885552f7358SJed Brown /*@
4886a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
4887552f7358SJed Brown 
4888552f7358SJed Brown   Not Collective
4889552f7358SJed Brown 
4890aa50250dSMatthew G. Knepley   Input Parameter:
4891a1cb98faSBarry Smith . dm    - The `DMPLEX` object
4892552f7358SJed Brown 
4893aa50250dSMatthew G. Knepley   Output Parameter:
4894a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
4895552f7358SJed Brown 
4896552f7358SJed Brown   Level: developer
4897552f7358SJed Brown 
48981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4899aa50250dSMatthew G. Knepley @*/
4900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4901d71ae5a4SJacob Faibussowitsch {
4902aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4903aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4904aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4905c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
49063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4907aa50250dSMatthew G. Knepley }
4908aa50250dSMatthew G. Knepley 
4909aa50250dSMatthew G. Knepley /*@
4910aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4911aa50250dSMatthew G. Knepley 
4912aa50250dSMatthew G. Knepley   Not Collective
4913aa50250dSMatthew G. Knepley 
4914aa50250dSMatthew G. Knepley   Input Parameter:
4915a1cb98faSBarry Smith . dm    - The `DMPLEX` object
4916aa50250dSMatthew G. Knepley 
4917aa50250dSMatthew G. Knepley   Output Parameter:
4918aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4919aa50250dSMatthew G. Knepley 
4920aa50250dSMatthew G. Knepley   Level: developer
4921552f7358SJed Brown 
4922b1bb481bSMatthew Knepley   Notes:
4923a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
4924a1cb98faSBarry Smith 
4925a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
4926a1cb98faSBarry Smith 
4927dc287ab2SVaclav Hapla   An empty mesh gives -1.
4928b1bb481bSMatthew Knepley 
49291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4930552f7358SJed Brown @*/
4931d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4932d71ae5a4SJacob Faibussowitsch {
49339f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4934aa50250dSMatthew G. Knepley   DMLabel  label;
4935aa50250dSMatthew G. Knepley   PetscInt d = 0;
4936552f7358SJed Brown 
4937552f7358SJed Brown   PetscFunctionBegin;
4938552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4939dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
49409f4ada15SMatthew G. Knepley   if (mesh->tr) {
49419f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
49429f4ada15SMatthew G. Knepley   } else {
49439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
49449566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
4945552f7358SJed Brown     *depth = d - 1;
49469f4ada15SMatthew G. Knepley   }
49473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4948552f7358SJed Brown }
4949552f7358SJed Brown 
4950552f7358SJed Brown /*@
495120f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
4952552f7358SJed Brown 
4953552f7358SJed Brown   Not Collective
4954552f7358SJed Brown 
4955552f7358SJed Brown   Input Parameters:
4956a1cb98faSBarry Smith + dm    - The `DMPLEX` object
4957570fa34dSVaclav Hapla - depth - The requested depth
4958552f7358SJed Brown 
4959552f7358SJed Brown   Output Parameters:
496020f4b53cSBarry Smith + start - The first point at this `depth`
496120f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
4962552f7358SJed Brown 
4963552f7358SJed Brown   Level: developer
4964552f7358SJed Brown 
4965a1cb98faSBarry Smith   Notes:
4966a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4967a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
4968a1cb98faSBarry Smith   higher dimension, e.g., "edges".
4969a1cb98faSBarry Smith 
49701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4971552f7358SJed Brown @*/
4972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
4973d71ae5a4SJacob Faibussowitsch {
49749f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4975aa50250dSMatthew G. Knepley   DMLabel  label;
497663d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
4977552f7358SJed Brown 
4978552f7358SJed Brown   PetscFunctionBegin;
4979552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49809371c9d4SSatish Balay   if (start) {
49819371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
49829371c9d4SSatish Balay     *start = 0;
49839371c9d4SSatish Balay   }
49849371c9d4SSatish Balay   if (end) {
49859371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
49869371c9d4SSatish Balay     *end = 0;
49879371c9d4SSatish Balay   }
49889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
49893ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
4990570fa34dSVaclav Hapla   if (depth < 0) {
499163d1a920SMatthew G. Knepley     if (start) *start = pStart;
499263d1a920SMatthew G. Knepley     if (end) *end = pEnd;
49933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
4994552f7358SJed Brown   }
49959f4ada15SMatthew G. Knepley   if (mesh->tr) {
49969f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
49979f4ada15SMatthew G. Knepley   } else {
49989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
499928b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5000570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
50019f4ada15SMatthew G. Knepley   }
50023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5003552f7358SJed Brown }
5004552f7358SJed Brown 
5005552f7358SJed Brown /*@
500620f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5007552f7358SJed Brown 
5008552f7358SJed Brown   Not Collective
5009552f7358SJed Brown 
5010552f7358SJed Brown   Input Parameters:
5011a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5012570fa34dSVaclav Hapla - height - The requested height
5013552f7358SJed Brown 
5014552f7358SJed Brown   Output Parameters:
501520f4b53cSBarry Smith + start - The first point at this `height`
501620f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5017552f7358SJed Brown 
5018552f7358SJed Brown   Level: developer
5019552f7358SJed Brown 
5020a1cb98faSBarry Smith   Notes:
5021a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5022a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5023a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5024a1cb98faSBarry Smith 
50251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5026552f7358SJed Brown @*/
5027d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5028d71ae5a4SJacob Faibussowitsch {
5029aa50250dSMatthew G. Knepley   DMLabel  label;
503063d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5031552f7358SJed Brown 
5032552f7358SJed Brown   PetscFunctionBegin;
5033552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50349371c9d4SSatish Balay   if (start) {
50359371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
50369371c9d4SSatish Balay     *start = 0;
50379371c9d4SSatish Balay   }
50389371c9d4SSatish Balay   if (end) {
50399371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
50409371c9d4SSatish Balay     *end = 0;
50419371c9d4SSatish Balay   }
50429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
50433ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5044570fa34dSVaclav Hapla   if (height < 0) {
504563d1a920SMatthew G. Knepley     if (start) *start = pStart;
504663d1a920SMatthew G. Knepley     if (end) *end = pEnd;
50473ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5048552f7358SJed Brown   }
50499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
505028b400f6SJacob Faibussowitsch   PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
50519566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
5052570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth - 1 - height, start, end));
50533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5054552f7358SJed Brown }
5055552f7358SJed Brown 
5056ba2698f1SMatthew G. Knepley /*@
505720f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5058ba2698f1SMatthew G. Knepley 
5059ba2698f1SMatthew G. Knepley   Not Collective
5060ba2698f1SMatthew G. Knepley 
5061d8d19677SJose E. Roman   Input Parameters:
5062a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5063ba2698f1SMatthew G. Knepley - point - The point
5064ba2698f1SMatthew G. Knepley 
5065ba2698f1SMatthew G. Knepley   Output Parameter:
506620f4b53cSBarry Smith . depth - The depth of the `point`
5067ba2698f1SMatthew G. Knepley 
5068ba2698f1SMatthew G. Knepley   Level: intermediate
5069ba2698f1SMatthew G. Knepley 
50701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5071ba2698f1SMatthew G. Knepley @*/
5072d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5073d71ae5a4SJacob Faibussowitsch {
5074ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5075ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
507640a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
50779566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
50783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5079ba2698f1SMatthew G. Knepley }
5080ba2698f1SMatthew G. Knepley 
5081ba2698f1SMatthew G. Knepley /*@
508220f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
50830c0a32dcSVaclav Hapla 
50840c0a32dcSVaclav Hapla   Not Collective
50850c0a32dcSVaclav Hapla 
5086d8d19677SJose E. Roman   Input Parameters:
5087a1cb98faSBarry Smith + dm    - The `DMPLEX` object
50880c0a32dcSVaclav Hapla - point - The point
50890c0a32dcSVaclav Hapla 
50900c0a32dcSVaclav Hapla   Output Parameter:
509120f4b53cSBarry Smith . height - The height of the `point`
50920c0a32dcSVaclav Hapla 
50930c0a32dcSVaclav Hapla   Level: intermediate
50940c0a32dcSVaclav Hapla 
50951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
50960c0a32dcSVaclav Hapla @*/
5097d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5098d71ae5a4SJacob Faibussowitsch {
50990c0a32dcSVaclav Hapla   PetscInt n, pDepth;
51000c0a32dcSVaclav Hapla 
51010c0a32dcSVaclav Hapla   PetscFunctionBegin;
51020c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51030c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
51049566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
51059566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
51060c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
51073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51080c0a32dcSVaclav Hapla }
51090c0a32dcSVaclav Hapla 
51100c0a32dcSVaclav Hapla /*@
5111a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5112ba2698f1SMatthew G. Knepley 
5113ba2698f1SMatthew G. Knepley   Not Collective
5114ba2698f1SMatthew G. Knepley 
5115ba2698f1SMatthew G. Knepley   Input Parameter:
5116a1cb98faSBarry Smith . dm - The `DMPLEX` object
5117ba2698f1SMatthew G. Knepley 
5118ba2698f1SMatthew G. Knepley   Output Parameter:
5119a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5120412e9a14SMatthew G. Knepley 
5121ba2698f1SMatthew G. Knepley   Level: developer
5122ba2698f1SMatthew G. Knepley 
5123a1cb98faSBarry Smith   Note:
5124a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5125a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5126a1cb98faSBarry Smith 
51271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5128ba2698f1SMatthew G. Knepley @*/
5129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5130d71ae5a4SJacob Faibussowitsch {
5131ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5132ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5133ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
51349566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5135ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
51363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5137ba2698f1SMatthew G. Knepley }
5138ba2698f1SMatthew G. Knepley 
5139ba2698f1SMatthew G. Knepley /*@
5140ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5141ba2698f1SMatthew G. Knepley 
5142ba2698f1SMatthew G. Knepley   Not Collective
5143ba2698f1SMatthew G. Knepley 
5144d8d19677SJose E. Roman   Input Parameters:
5145a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5146ba2698f1SMatthew G. Knepley - cell - The cell
5147ba2698f1SMatthew G. Knepley 
5148ba2698f1SMatthew G. Knepley   Output Parameter:
5149ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5150ba2698f1SMatthew G. Knepley 
5151ba2698f1SMatthew G. Knepley   Level: intermediate
5152ba2698f1SMatthew G. Knepley 
51531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5154ba2698f1SMatthew G. Knepley @*/
5155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5156d71ae5a4SJacob Faibussowitsch {
51579f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5158ba2698f1SMatthew G. Knepley   DMLabel  label;
5159ba2698f1SMatthew G. Knepley   PetscInt ct;
5160ba2698f1SMatthew G. Knepley 
5161ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5162ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5163ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
51649f4ada15SMatthew G. Knepley   if (mesh->tr) {
51659f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
51669f4ada15SMatthew G. Knepley   } else {
51679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
51689566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, cell, &ct));
516963a3b9bcSJacob Faibussowitsch     PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5170ba2698f1SMatthew G. Knepley     *celltype = (DMPolytopeType)ct;
51719f4ada15SMatthew G. Knepley   }
51723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5173ba2698f1SMatthew G. Knepley }
5174ba2698f1SMatthew G. Knepley 
5175412e9a14SMatthew G. Knepley /*@
5176412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5177412e9a14SMatthew G. Knepley 
5178412e9a14SMatthew G. Knepley   Not Collective
5179412e9a14SMatthew G. Knepley 
5180412e9a14SMatthew G. Knepley   Input Parameters:
5181a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5182412e9a14SMatthew G. Knepley . cell - The cell
5183412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5184412e9a14SMatthew G. Knepley 
5185a1cb98faSBarry Smith   Level: advanced
5186a1cb98faSBarry Smith 
5187a1cb98faSBarry Smith   Note:
5188a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5189412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5190412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5191412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
5192412e9a14SMatthew G. Knepley 
51931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5194412e9a14SMatthew G. Knepley @*/
5195d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5196d71ae5a4SJacob Faibussowitsch {
5197412e9a14SMatthew G. Knepley   DMLabel label;
5198412e9a14SMatthew G. Knepley 
5199412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5200412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
52029566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
52033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5204412e9a14SMatthew G. Knepley }
5205412e9a14SMatthew G. Knepley 
5206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5207d71ae5a4SJacob Faibussowitsch {
5208efe440bfSMatthew G. Knepley   PetscSection section, s;
5209efe440bfSMatthew G. Knepley   Mat          m;
52103e922f36SToby Isaac   PetscInt     maxHeight;
5211dd4c3f67SMatthew G. Knepley   const char  *prefix;
5212552f7358SJed Brown 
5213552f7358SJed Brown   PetscFunctionBegin;
52149566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5215dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5216dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5217dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
52189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
52199566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
52209566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
52219566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
52229566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
52239566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
52249566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
52259566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
52269566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
52279566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
52288f4c458bSMatthew G. Knepley 
52299566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
52309566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5231dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5232dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
52333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5234552f7358SJed Brown }
5235552f7358SJed Brown 
5236d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5237d71ae5a4SJacob Faibussowitsch {
52386858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
52396858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5240f19dbd58SToby Isaac 
5241f19dbd58SToby Isaac   PetscFunctionBegin;
5242f19dbd58SToby Isaac   *field = NULL;
52439566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
52449566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
52456858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
52466858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5247f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
52486858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
52496858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5250f19dbd58SToby Isaac   }
52513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5252f19dbd58SToby Isaac }
5253f19dbd58SToby Isaac 
52547cd05799SMatthew G. Knepley /*@C
52557cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
52567cd05799SMatthew G. Knepley 
52577cd05799SMatthew G. Knepley   Not Collective
52587cd05799SMatthew G. Knepley 
52592fe279fdSBarry Smith   Input Parameter:
5260a1cb98faSBarry Smith . dm        - The `DMPLEX` object
52617cd05799SMatthew G. Knepley 
52627cd05799SMatthew G. Knepley   Output Parameter:
5263a1cb98faSBarry Smith . section - The `PetscSection` object
52647cd05799SMatthew G. Knepley 
52657cd05799SMatthew G. Knepley   Level: developer
52667cd05799SMatthew G. Knepley 
52671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
52687cd05799SMatthew G. Knepley @*/
5269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5270d71ae5a4SJacob Faibussowitsch {
5271552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5272552f7358SJed Brown 
5273552f7358SJed Brown   PetscFunctionBegin;
5274552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5275552f7358SJed Brown   if (section) *section = mesh->coneSection;
52763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5277552f7358SJed Brown }
5278552f7358SJed Brown 
52797cd05799SMatthew G. Knepley /*@C
52807cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
52817cd05799SMatthew G. Knepley 
52827cd05799SMatthew G. Knepley   Not Collective
52837cd05799SMatthew G. Knepley 
52842fe279fdSBarry Smith   Input Parameter:
5285a1cb98faSBarry Smith . dm        - The `DMPLEX` object
52867cd05799SMatthew G. Knepley 
52877cd05799SMatthew G. Knepley   Output Parameter:
5288a1cb98faSBarry Smith . section - The `PetscSection` object
52897cd05799SMatthew G. Knepley 
52907cd05799SMatthew G. Knepley   Level: developer
52917cd05799SMatthew G. Knepley 
52921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
52937cd05799SMatthew G. Knepley @*/
5294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5295d71ae5a4SJacob Faibussowitsch {
52968cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
52978cb4d582SMatthew G. Knepley 
52988cb4d582SMatthew G. Knepley   PetscFunctionBegin;
52998cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53008cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
53013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53028cb4d582SMatthew G. Knepley }
53038cb4d582SMatthew G. Knepley 
53047cd05799SMatthew G. Knepley /*@C
53057cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
53067cd05799SMatthew G. Knepley 
53077cd05799SMatthew G. Knepley   Not Collective
53087cd05799SMatthew G. Knepley 
53092fe279fdSBarry Smith   Input Parameter:
5310a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53117cd05799SMatthew G. Knepley 
53127cd05799SMatthew G. Knepley   Output Parameter:
53137cd05799SMatthew G. Knepley . cones - The cone for each point
53147cd05799SMatthew G. Knepley 
53157cd05799SMatthew G. Knepley   Level: developer
53167cd05799SMatthew G. Knepley 
53171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
53187cd05799SMatthew G. Knepley @*/
5319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5320d71ae5a4SJacob Faibussowitsch {
5321552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5322552f7358SJed Brown 
5323552f7358SJed Brown   PetscFunctionBegin;
5324552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5325552f7358SJed Brown   if (cones) *cones = mesh->cones;
53263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5327552f7358SJed Brown }
5328552f7358SJed Brown 
53297cd05799SMatthew G. Knepley /*@C
53307cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
53317cd05799SMatthew G. Knepley 
53327cd05799SMatthew G. Knepley   Not Collective
53337cd05799SMatthew G. Knepley 
53342fe279fdSBarry Smith   Input Parameter:
5335a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53367cd05799SMatthew G. Knepley 
53377cd05799SMatthew G. Knepley   Output Parameter:
5338b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
53397cd05799SMatthew G. Knepley 
53407cd05799SMatthew G. Knepley   Level: developer
53417cd05799SMatthew G. Knepley 
5342b5a892a1SMatthew G. Knepley   Notes:
5343a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5344b5a892a1SMatthew G. Knepley 
5345a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5346b5a892a1SMatthew G. Knepley 
53471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
53487cd05799SMatthew G. Knepley @*/
5349d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5350d71ae5a4SJacob Faibussowitsch {
5351552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5352552f7358SJed Brown 
5353552f7358SJed Brown   PetscFunctionBegin;
5354552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5355552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
53563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5357552f7358SJed Brown }
5358552f7358SJed Brown 
5359552f7358SJed Brown /******************************** FEM Support **********************************/
5360552f7358SJed Brown 
53619e8305c2SJed Brown /*
53629e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
53639e8305c2SJed Brown  representing a line in the section.
53649e8305c2SJed Brown */
5365d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k)
5366d71ae5a4SJacob Faibussowitsch {
53679e8305c2SJed Brown   PetscFunctionBeginHot;
53689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5369a433471fSStefano Zampini   if (line < 0) {
5370a433471fSStefano Zampini     *k  = 0;
5371a433471fSStefano Zampini     *Nc = 0;
5372a433471fSStefano Zampini   } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */
53739e8305c2SJed Brown     *k = 1;
53749e8305c2SJed Brown   } else { /* Assume the full interpolated mesh is in the chart; lines in particular */
53759e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
53769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
53779e8305c2SJed Brown     *k = *k / *Nc + 1;
53789e8305c2SJed Brown   }
53793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53809e8305c2SJed Brown }
53819e8305c2SJed Brown 
5382a4355906SMatthew Knepley /*@
5383bc1eb3faSJed Brown 
5384bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5385bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
538620f4b53cSBarry Smith   section provided (or the section of the `DM`).
5387a4355906SMatthew Knepley 
5388a4355906SMatthew Knepley   Input Parameters:
538920f4b53cSBarry Smith + dm      - The `DM`
539020f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
539120f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5392a4355906SMatthew Knepley 
5393bc1eb3faSJed Brown   Example:
5394bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5395bc1eb3faSJed Brown .vb
5396bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5397bc1eb3faSJed Brown 
5398bc1eb3faSJed Brown   v4 -- e6 -- v3
5399bc1eb3faSJed Brown   |           |
5400bc1eb3faSJed Brown   e7    c0    e8
5401bc1eb3faSJed Brown   |           |
5402bc1eb3faSJed Brown   v1 -- e5 -- v2
5403bc1eb3faSJed Brown .ve
5404bc1eb3faSJed Brown 
5405bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5406bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5407bc1eb3faSJed Brown .vb
5408bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5409bc1eb3faSJed Brown     v1 -> [4]
5410bc1eb3faSJed Brown     ...
5411bc1eb3faSJed Brown     e5 -> [8, 9]
5412bc1eb3faSJed Brown .ve
5413bc1eb3faSJed Brown 
5414bc1eb3faSJed Brown   which corresponds to the dofs
5415bc1eb3faSJed Brown .vb
5416bc1eb3faSJed Brown     6   10  11  7
5417bc1eb3faSJed Brown     13  2   3   15
5418bc1eb3faSJed Brown     12  0   1   14
5419bc1eb3faSJed Brown     4   8   9   5
5420bc1eb3faSJed Brown .ve
5421bc1eb3faSJed Brown 
5422bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5423bc1eb3faSJed Brown .vb
5424bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5425bc1eb3faSJed Brown .ve
5426bc1eb3faSJed Brown 
5427bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5428bc1eb3faSJed Brown .vb
5429bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5430bc1eb3faSJed Brown .ve
5431bc1eb3faSJed Brown 
5432a4355906SMatthew Knepley   Level: developer
5433a4355906SMatthew Knepley 
5434a1cb98faSBarry Smith   Note:
5435a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5436a1cb98faSBarry Smith   degree of the basis.
5437a1cb98faSBarry Smith 
54381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5439a4355906SMatthew Knepley @*/
5440d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5441d71ae5a4SJacob Faibussowitsch {
54427391a63aSMatthew G. Knepley   DMLabel   label;
5443bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
54449e8305c2SJed Brown   PetscBool vertexchart;
54453194fc30SMatthew G. Knepley 
54463194fc30SMatthew G. Knepley   PetscFunctionBegin;
54479566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
54483ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5449a433471fSStefano Zampini   if (point < 0) {
5450a433471fSStefano Zampini     PetscInt sStart, sEnd;
5451a433471fSStefano Zampini 
54529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5453a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5454a433471fSStefano Zampini   }
54559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
54569566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
54579566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
54589371c9d4SSatish Balay   if (depth == 1) {
54599371c9d4SSatish Balay     eStart = point;
54609371c9d4SSatish Balay   } else if (depth == dim) {
54617391a63aSMatthew G. Knepley     const PetscInt *cone;
54627391a63aSMatthew G. Knepley 
54639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5464d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5465d4e6627bSStefano Zampini     else if (dim == 3) {
5466d4e6627bSStefano Zampini       const PetscInt *cone2;
54679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5468d4e6627bSStefano Zampini       eStart = cone2[0];
546963a3b9bcSJacob 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);
547063a3b9bcSJacob 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);
54719e8305c2SJed Brown   { /* Determine whether the chart covers all points or just vertices. */
54729e8305c2SJed Brown     PetscInt pStart, pEnd, cStart, cEnd;
54739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd));
54749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section, &cStart, &cEnd));
5475796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5476796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5477796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
54789e8305c2SJed Brown   }
54799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5480bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5481bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5482bb197d40SJed Brown     PetscInt *perm;
5483bb197d40SJed Brown 
54843194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
54859566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5486bb197d40SJed Brown       size += PetscPowInt(k + 1, d) * Nc;
54873194fc30SMatthew G. Knepley     }
54889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
54893194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5490bb197d40SJed Brown       switch (d) {
5491babf31e0SJed Brown       case 1:
54929566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5493babf31e0SJed Brown         /*
5494babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5495babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5496babf31e0SJed Brown          */
5497babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
54989371c9d4SSatish Balay         for (i = 0; i < k - 1; i++)
54999371c9d4SSatish Balay           for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5500babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5501babf31e0SJed Brown         foffset = offset;
5502babf31e0SJed Brown         break;
550389eabcffSMatthew G. Knepley       case 2:
55043194fc30SMatthew 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} */
55059566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
55063194fc30SMatthew G. Knepley         /* The SEM order is
55073194fc30SMatthew G. Knepley 
55083194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
550989eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
55103194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
55113194fc30SMatthew G. Knepley          */
55123194fc30SMatthew G. Knepley         {
55133194fc30SMatthew G. Knepley           const PetscInt of   = 0;
55143194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
55153194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
55163194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
55173194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
55183194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
55193194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
55203194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
55213194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
55223194fc30SMatthew G. Knepley           PetscInt       o;
55233194fc30SMatthew G. Knepley 
55243194fc30SMatthew G. Knepley           /* bottom */
55253194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
55269371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
55279371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55283194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
55293194fc30SMatthew G. Knepley           /* middle */
55303194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
55313194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
55329371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
55339371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55343194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
55353194fc30SMatthew G. Knepley           }
55363194fc30SMatthew G. Knepley           /* top */
55373194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
55389371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
55399371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55403194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
55413194fc30SMatthew G. Knepley           foffset = offset;
55423194fc30SMatthew G. Knepley         }
554389eabcffSMatthew G. Knepley         break;
554489eabcffSMatthew G. Knepley       case 3:
554589eabcffSMatthew G. Knepley         /* The original hex closure is
554689eabcffSMatthew G. Knepley 
554789eabcffSMatthew G. Knepley          {c,
554889eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
554989eabcffSMatthew 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,
555089eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
555189eabcffSMatthew G. Knepley          */
55529566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
555389eabcffSMatthew G. Knepley         /* The SEM order is
555489eabcffSMatthew G. Knepley          Bottom Slice
555589eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
555689eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
555789eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
555889eabcffSMatthew G. Knepley 
555989eabcffSMatthew G. Knepley          Middle Slice (j)
556089eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
556189eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
556289eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
556389eabcffSMatthew G. Knepley 
556489eabcffSMatthew G. Knepley          Top Slice
556589eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
556689eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
556789eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
556889eabcffSMatthew G. Knepley          */
556989eabcffSMatthew G. Knepley         {
557089eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
557189eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
557289eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
557389eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
557489eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
557589eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
557689eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
557789eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
557889eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
557989eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
558089eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
558189eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
558289eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
558389eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
558489eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
558589eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
558689eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
558789eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
558889eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
558989eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
559089eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
559189eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
559289eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
559389eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
559489eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
559589eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
559689eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
559789eabcffSMatthew G. Knepley           PetscInt       o, n;
559889eabcffSMatthew G. Knepley 
559989eabcffSMatthew G. Knepley           /* Bottom Slice */
560089eabcffSMatthew G. Knepley           /*   bottom */
560189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
56029371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
56039371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
560489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
560589eabcffSMatthew G. Knepley           /*   middle */
560689eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
560789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
56089371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
56099371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
56109371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56119371c9d4SSatish Balay             }
561289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
56133194fc30SMatthew G. Knepley           }
561489eabcffSMatthew G. Knepley           /*   top */
561589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
56169371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
56179371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
561889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
561989eabcffSMatthew G. Knepley 
562089eabcffSMatthew G. Knepley           /* Middle Slice */
562189eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
562289eabcffSMatthew G. Knepley             /*   bottom */
562389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
56249371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
56259371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
562689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
562789eabcffSMatthew G. Knepley             /*   middle */
562889eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
562989eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
56309371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
56319371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
563289eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
563389eabcffSMatthew G. Knepley             }
563489eabcffSMatthew G. Knepley             /*   top */
563589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
56369371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
56379371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
563889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
563989eabcffSMatthew G. Knepley           }
564089eabcffSMatthew G. Knepley 
564189eabcffSMatthew G. Knepley           /* Top Slice */
564289eabcffSMatthew G. Knepley           /*   bottom */
564389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
56449371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
56459371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
564689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
564789eabcffSMatthew G. Knepley           /*   middle */
564889eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
564989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
56509371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
56519371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
565289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
565389eabcffSMatthew G. Knepley           }
565489eabcffSMatthew G. Knepley           /*   top */
565589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
56569371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
56579371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
565889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
565989eabcffSMatthew G. Knepley 
566089eabcffSMatthew G. Knepley           foffset = offset;
566189eabcffSMatthew G. Knepley         }
566289eabcffSMatthew G. Knepley         break;
5663d71ae5a4SJacob Faibussowitsch       default:
5664d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
566589eabcffSMatthew G. Knepley       }
566689eabcffSMatthew G. Knepley     }
566763a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
56683194fc30SMatthew G. Knepley     /* Check permutation */
56693194fc30SMatthew G. Knepley     {
56703194fc30SMatthew G. Knepley       PetscInt *check;
56713194fc30SMatthew G. Knepley 
56729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
56731dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
56741dca8a05SBarry Smith         check[i] = -1;
56751dca8a05SBarry 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]);
56761dca8a05SBarry Smith       }
56773194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
56781dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
56799566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
56803194fc30SMatthew G. Knepley     }
56819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
5682a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5683a05c9aa3SJed Brown       PetscInt *loc_perm;
56849566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
5685a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
5686a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
5687a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
5688a05c9aa3SJed Brown       }
56899566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
5690a05c9aa3SJed Brown     }
5691bb197d40SJed Brown   }
56923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56933194fc30SMatthew G. Knepley }
56943194fc30SMatthew G. Knepley 
5695d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5696d71ae5a4SJacob Faibussowitsch {
5697e071409bSToby Isaac   PetscDS  prob;
5698e071409bSToby Isaac   PetscInt depth, Nf, h;
5699e071409bSToby Isaac   DMLabel  label;
5700e071409bSToby Isaac 
5701e071409bSToby Isaac   PetscFunctionBeginHot;
57029566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5703e071409bSToby Isaac   Nf      = prob->Nf;
5704e071409bSToby Isaac   label   = dm->depthLabel;
5705e071409bSToby Isaac   *dspace = NULL;
5706e071409bSToby Isaac   if (field < Nf) {
5707e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5708e071409bSToby Isaac 
5709e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5710e071409bSToby Isaac       PetscDualSpace dsp;
5711e071409bSToby Isaac 
57129566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
57139566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
57149566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
5715e071409bSToby Isaac       h = depth - 1 - h;
5716e071409bSToby Isaac       if (h) {
57179566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
5718e071409bSToby Isaac       } else {
5719e071409bSToby Isaac         *dspace = dsp;
5720e071409bSToby Isaac       }
5721e071409bSToby Isaac     }
5722e071409bSToby Isaac   }
57233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5724e071409bSToby Isaac }
5725e071409bSToby Isaac 
5726d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5727d71ae5a4SJacob Faibussowitsch {
572828351e22SJed Brown   PetscScalar       *array;
572928351e22SJed Brown   const PetscScalar *vArray;
5730d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
57311a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
5732552f7358SJed Brown 
57331b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
57349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
57359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
57369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
57379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
57383f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
57399df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
57409df71ca4SMatthew G. Knepley       PetscInt dof;
5741d9917b9dSMatthew G. Knepley 
57429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
57439df71ca4SMatthew G. Knepley       size += dof;
57449df71ca4SMatthew G. Knepley     }
57459df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
57469df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
57472a3aaacfSMatthew G. Knepley       PetscInt       dof;
57485a1bb5cfSMatthew G. Knepley 
57495a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
57509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
57515a1bb5cfSMatthew G. Knepley       size += dof;
57525a1bb5cfSMatthew G. Knepley     }
57533f7cbbe7SMatthew G. Knepley     if (!values) {
57543f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
57553ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
57563f7cbbe7SMatthew G. Knepley     }
57579566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5758982e9ed1SMatthew G. Knepley   } else {
5759982e9ed1SMatthew G. Knepley     array = *values;
5760982e9ed1SMatthew G. Knepley   }
57619df71ca4SMatthew G. Knepley   size = 0;
576228351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
57639df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
57649df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
576528351e22SJed Brown     const PetscScalar *varr;
5766d9917b9dSMatthew G. Knepley 
57679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
57689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
57699df71ca4SMatthew G. Knepley     varr = &vArray[off];
5770ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
57719df71ca4SMatthew G. Knepley     size += dof;
57729df71ca4SMatthew G. Knepley   }
57739df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
57749df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
57759df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
57765a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
577728351e22SJed Brown     const PetscScalar *varr;
57785a1bb5cfSMatthew G. Knepley 
577952ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
57809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
57819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
57825a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
57835a1bb5cfSMatthew G. Knepley     if (o >= 0) {
5784ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
57855a1bb5cfSMatthew G. Knepley     } else {
5786ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
57875a1bb5cfSMatthew G. Knepley     }
57889df71ca4SMatthew G. Knepley     size += dof;
57895a1bb5cfSMatthew G. Knepley   }
579028351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
57919df71ca4SMatthew G. Knepley   if (!*values) {
57925a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
57935a1bb5cfSMatthew G. Knepley     *values = array;
57949df71ca4SMatthew G. Knepley   } else {
579563a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
57968c312ff3SMatthew G. Knepley     *csize = size;
57979df71ca4SMatthew G. Knepley   }
57983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57995a1bb5cfSMatthew G. Knepley }
5800d9917b9dSMatthew G. Knepley 
580127f02ce8SMatthew G. Knepley /* Compress out points not in the section */
5802d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
5803d71ae5a4SJacob Faibussowitsch {
580427f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
580527f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
580627f02ce8SMatthew G. Knepley 
58079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
580827f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
580927f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
581027f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
581127f02ce8SMatthew G. Knepley       points[q * 2]     = r;
581227f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
581327f02ce8SMatthew G. Knepley       ++q;
581427f02ce8SMatthew G. Knepley     }
581527f02ce8SMatthew G. Knepley   }
581627f02ce8SMatthew G. Knepley   *numPoints = q;
58173ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
581827f02ce8SMatthew G. Knepley }
581927f02ce8SMatthew G. Knepley 
582097529cf3SJed Brown /* Compressed closure does not apply closure permutation */
582107218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5822d71ae5a4SJacob Faibussowitsch {
582327f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5824923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
5825923c78e0SToby Isaac 
5826923c78e0SToby Isaac   PetscFunctionBeginHot;
58279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
582807218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
5829923c78e0SToby Isaac     PetscInt dof, off;
5830923c78e0SToby Isaac 
58319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
58329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
58339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5834923c78e0SToby Isaac     np  = dof / 2;
5835923c78e0SToby Isaac     pts = (PetscInt *)&cla[off];
583627f02ce8SMatthew G. Knepley   } else {
583707218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
58389566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5839923c78e0SToby Isaac   }
5840923c78e0SToby Isaac   *numPoints = np;
5841923c78e0SToby Isaac   *points    = pts;
5842923c78e0SToby Isaac   *clp       = cla;
58433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5844923c78e0SToby Isaac }
5845923c78e0SToby Isaac 
5846d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5847d71ae5a4SJacob Faibussowitsch {
5848923c78e0SToby Isaac   PetscFunctionBeginHot;
5849923c78e0SToby Isaac   if (!*clPoints) {
58509566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5851923c78e0SToby Isaac   } else {
58529566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5853923c78e0SToby Isaac   }
5854923c78e0SToby Isaac   *numPoints = 0;
5855923c78e0SToby Isaac   *points    = NULL;
5856923c78e0SToby Isaac   *clSec     = NULL;
5857923c78e0SToby Isaac   *clPoints  = NULL;
5858923c78e0SToby Isaac   *clp       = NULL;
58593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5860923c78e0SToby Isaac }
5861923c78e0SToby Isaac 
5862d71ae5a4SJacob 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[])
5863d71ae5a4SJacob Faibussowitsch {
58641a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
586597e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
586697e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
58671a271a75SMatthew G. Knepley 
58681a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5869fe02ba77SJed Brown   *size = 0;
58709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
587197e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
587297e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
587397e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
587497e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
58751a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
58761a271a75SMatthew G. Knepley     const PetscScalar *varr;
58771a271a75SMatthew G. Knepley 
58789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
58799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
58801a271a75SMatthew G. Knepley     varr = &vArray[off];
588197e99dd9SToby Isaac     if (clperm) {
588297e99dd9SToby Isaac       if (perm) {
588397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
58841a271a75SMatthew G. Knepley       } else {
588597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
588697e99dd9SToby Isaac       }
588797e99dd9SToby Isaac       if (flip) {
588897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
588997e99dd9SToby Isaac       }
589097e99dd9SToby Isaac     } else {
589197e99dd9SToby Isaac       if (perm) {
589297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
589397e99dd9SToby Isaac       } else {
589497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
589597e99dd9SToby Isaac       }
589697e99dd9SToby Isaac       if (flip) {
589797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
58981a271a75SMatthew G. Knepley       }
58991a271a75SMatthew G. Knepley     }
590097e99dd9SToby Isaac     offset += dof;
590197e99dd9SToby Isaac   }
59029566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
59031a271a75SMatthew G. Knepley   *size = offset;
59043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59051a271a75SMatthew G. Knepley }
59061a271a75SMatthew G. Knepley 
5907d71ae5a4SJacob 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[])
5908d71ae5a4SJacob Faibussowitsch {
59091a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
59101a271a75SMatthew G. Knepley 
59111a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5912fe02ba77SJed Brown   *size = 0;
59131a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
591497e99dd9SToby Isaac     PetscInt            p;
591597e99dd9SToby Isaac     const PetscInt    **perms = NULL;
591697e99dd9SToby Isaac     const PetscScalar **flips = NULL;
59171a271a75SMatthew G. Knepley 
59189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
591997e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
592097e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
592197e99dd9SToby Isaac       PetscInt           fdof, foff, b;
59221a271a75SMatthew G. Knepley       const PetscScalar *varr;
592397e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
592497e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
59251a271a75SMatthew G. Knepley 
59269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
59279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
59281a271a75SMatthew G. Knepley       varr = &vArray[foff];
592997e99dd9SToby Isaac       if (clperm) {
59309371c9d4SSatish Balay         if (perm) {
5931ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
59321a271a75SMatthew G. Knepley         } else {
5933ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
59349371c9d4SSatish Balay         }
59359371c9d4SSatish Balay         if (flip) {
5936ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
59379371c9d4SSatish Balay         }
59389371c9d4SSatish Balay       } else {
59399371c9d4SSatish Balay         if (perm) {
5940ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
59419371c9d4SSatish Balay         } else {
5942ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
59439371c9d4SSatish Balay         }
59449371c9d4SSatish Balay         if (flip) {
5945ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
59469371c9d4SSatish Balay         }
59471a271a75SMatthew G. Knepley       }
594897e99dd9SToby Isaac       offset += fdof;
59491a271a75SMatthew G. Knepley     }
59509566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
59511a271a75SMatthew G. Knepley   }
59521a271a75SMatthew G. Knepley   *size = offset;
59533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59541a271a75SMatthew G. Knepley }
59551a271a75SMatthew G. Knepley 
595607218a29SMatthew G. Knepley PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
595707218a29SMatthew G. Knepley {
595807218a29SMatthew G. Knepley   PetscSection    clSection;
595907218a29SMatthew G. Knepley   IS              clPoints;
596007218a29SMatthew G. Knepley   PetscInt       *points = NULL;
596107218a29SMatthew G. Knepley   const PetscInt *clp, *perm;
596207218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
596307218a29SMatthew G. Knepley 
596407218a29SMatthew G. Knepley   PetscFunctionBeginHot;
596507218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
596607218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
596707218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
596807218a29SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
596907218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
597007218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
597107218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
597207218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
597307218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
597407218a29SMatthew G. Knepley   }
597507218a29SMatthew G. Knepley   /* Get points */
597607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
597707218a29SMatthew G. Knepley   /* Get sizes */
597807218a29SMatthew G. Knepley   asize = 0;
597907218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
598007218a29SMatthew G. Knepley     PetscInt dof;
598107218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
598207218a29SMatthew G. Knepley     asize += dof;
598307218a29SMatthew G. Knepley   }
598407218a29SMatthew G. Knepley   if (values) {
598507218a29SMatthew G. Knepley     const PetscScalar *vArray;
598607218a29SMatthew G. Knepley     PetscInt           size;
598707218a29SMatthew G. Knepley 
598807218a29SMatthew G. Knepley     if (*values) {
598907218a29SMatthew 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);
599007218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
599107218a29SMatthew G. Knepley     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
599207218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
599307218a29SMatthew G. Knepley     /* Get values */
599407218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
599507218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
599607218a29SMatthew 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);
599707218a29SMatthew G. Knepley     /* Cleanup array */
599807218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
599907218a29SMatthew G. Knepley   }
600007218a29SMatthew G. Knepley   if (csize) *csize = asize;
600107218a29SMatthew G. Knepley   /* Cleanup points */
600207218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
600307218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
600407218a29SMatthew G. Knepley }
600507218a29SMatthew G. Knepley 
6006552f7358SJed Brown /*@C
6007552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6008552f7358SJed Brown 
6009552f7358SJed Brown   Not collective
6010552f7358SJed Brown 
6011552f7358SJed Brown   Input Parameters:
6012a1cb98faSBarry Smith + dm - The `DM`
601320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6014552f7358SJed Brown . v - The local vector
6015a1cb98faSBarry Smith - point - The point in the `DM`
6016552f7358SJed Brown 
60176b867d5aSJose E. Roman   Input/Output Parameters:
601820f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
601920f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
602020f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
602122c1ee49SMatthew G. Knepley 
6022552f7358SJed Brown   Level: intermediate
6023552f7358SJed Brown 
6024a1cb98faSBarry Smith   Notes:
602520f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6026a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6027a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6028a1cb98faSBarry Smith 
6029a1cb98faSBarry Smith   A typical use could be
6030a1cb98faSBarry Smith .vb
6031a1cb98faSBarry Smith    values = NULL;
6032a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6033a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6034a1cb98faSBarry Smith      <Compute on closure>
6035a1cb98faSBarry Smith    }
6036a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6037a1cb98faSBarry Smith .ve
6038a1cb98faSBarry Smith   or
6039a1cb98faSBarry Smith .vb
6040a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6041a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6042a1cb98faSBarry Smith      clSize = clMaxSize;
6043a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6044a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6045a1cb98faSBarry Smith        <Compute on closure>
6046a1cb98faSBarry Smith      }
6047a1cb98faSBarry Smith    }
6048a1cb98faSBarry Smith    PetscFree(values);
6049a1cb98faSBarry Smith .ve
6050a1cb98faSBarry Smith 
6051a1cb98faSBarry Smith   Fortran Note:
605220f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6053a1cb98faSBarry Smith 
60541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6055552f7358SJed Brown @*/
6056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6057d71ae5a4SJacob Faibussowitsch {
6058d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
605907218a29SMatthew G. Knepley   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, v, point, 0, csize, values));
60603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6061552f7358SJed Brown }
6062552f7358SJed Brown 
6063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6064d71ae5a4SJacob Faibussowitsch {
6065e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6066e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6067e5c487bfSMatthew G. Knepley   IS                 clPoints;
6068e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6069e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6070e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6071c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6072c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6073e5c487bfSMatthew G. Knepley 
6074e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6075e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
60769566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6077e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6078e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
60799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
60809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
60819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6082e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
60839566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
60843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6085e5c487bfSMatthew G. Knepley   }
6086e5c487bfSMatthew G. Knepley   /* Get points */
608707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6088c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6089c459fbc1SJed Brown     PetscInt dof;
60909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6091c459fbc1SJed Brown     clsize += dof;
6092c459fbc1SJed Brown   }
60939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6094e5c487bfSMatthew G. Knepley   /* Filter points */
6095e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6096e5c487bfSMatthew G. Knepley     PetscInt dep;
6097e5c487bfSMatthew G. Knepley 
60989566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6099e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6100e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6101e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6102e5c487bfSMatthew G. Knepley     ++Np;
6103e5c487bfSMatthew G. Knepley   }
6104e5c487bfSMatthew G. Knepley   /* Get array */
6105e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6106e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6107e5c487bfSMatthew G. Knepley 
6108e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
61099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6110e5c487bfSMatthew G. Knepley       asize += dof;
6111e5c487bfSMatthew G. Knepley     }
6112e5c487bfSMatthew G. Knepley     if (!values) {
61139566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6114e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
61153ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6116e5c487bfSMatthew G. Knepley     }
61179566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6118e5c487bfSMatthew G. Knepley   } else {
6119e5c487bfSMatthew G. Knepley     array = *values;
6120e5c487bfSMatthew G. Knepley   }
61219566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6122e5c487bfSMatthew G. Knepley   /* Get values */
61239566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
61249566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6125e5c487bfSMatthew G. Knepley   /* Cleanup points */
61269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6127e5c487bfSMatthew G. Knepley   /* Cleanup array */
61289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6129e5c487bfSMatthew G. Knepley   if (!*values) {
6130e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6131e5c487bfSMatthew G. Knepley     *values = array;
6132e5c487bfSMatthew G. Knepley   } else {
613363a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6134e5c487bfSMatthew G. Knepley     *csize = size;
6135e5c487bfSMatthew G. Knepley   }
61363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6137e5c487bfSMatthew G. Knepley }
6138e5c487bfSMatthew G. Knepley 
6139552f7358SJed Brown /*@C
6140552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6141552f7358SJed Brown 
6142552f7358SJed Brown   Not collective
6143552f7358SJed Brown 
6144552f7358SJed Brown   Input Parameters:
6145a1cb98faSBarry Smith + dm - The `DM`
614620f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6147552f7358SJed Brown . v - The local vector
6148a1cb98faSBarry Smith . point - The point in the `DM`
614920f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL`
6150552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
6151552f7358SJed Brown 
6152552f7358SJed Brown   Level: intermediate
6153552f7358SJed Brown 
6154a1cb98faSBarry Smith   Note:
615520f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6156a1cb98faSBarry Smith 
6157a1cb98faSBarry Smith   Fortran Note:
615820f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6159a1cb98faSBarry Smith 
61601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6161552f7358SJed Brown @*/
6162d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6163d71ae5a4SJacob Faibussowitsch {
6164552f7358SJed Brown   PetscInt size = 0;
6165552f7358SJed Brown 
6166552f7358SJed Brown   PetscFunctionBegin;
6167552f7358SJed Brown   /* Should work without recalculating size */
61689566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6169c9fdaa05SMatthew G. Knepley   *values = NULL;
61703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6171552f7358SJed Brown }
6172552f7358SJed Brown 
6173d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6174d71ae5a4SJacob Faibussowitsch {
61759371c9d4SSatish Balay   *x += y;
61769371c9d4SSatish Balay }
6177d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6178d71ae5a4SJacob Faibussowitsch {
61799371c9d4SSatish Balay   *x = y;
61809371c9d4SSatish Balay }
6181552f7358SJed Brown 
6182d71ae5a4SJacob 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[])
6183d71ae5a4SJacob Faibussowitsch {
6184552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6185552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6186552f7358SJed Brown   PetscScalar    *a;
6187552f7358SJed Brown   PetscInt        off, cind = 0, k;
6188552f7358SJed Brown 
6189552f7358SJed Brown   PetscFunctionBegin;
61909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
61919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6192552f7358SJed Brown   a = &array[off];
6193552f7358SJed Brown   if (!cdof || setBC) {
619497e99dd9SToby Isaac     if (clperm) {
61959371c9d4SSatish Balay       if (perm) {
6196ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6197552f7358SJed Brown       } else {
6198ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
61999371c9d4SSatish Balay       }
62009371c9d4SSatish Balay     } else {
62019371c9d4SSatish Balay       if (perm) {
6202ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
62039371c9d4SSatish Balay       } else {
6204ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
62059371c9d4SSatish Balay       }
6206552f7358SJed Brown     }
6207552f7358SJed Brown   } else {
62089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
620997e99dd9SToby Isaac     if (clperm) {
62109371c9d4SSatish Balay       if (perm) {
62119371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
62129371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62139371c9d4SSatish Balay             ++cind;
62149371c9d4SSatish Balay             continue;
62159371c9d4SSatish Balay           }
621697e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6217552f7358SJed Brown         }
6218552f7358SJed Brown       } else {
6219552f7358SJed Brown         for (k = 0; k < dof; ++k) {
62209371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62219371c9d4SSatish Balay             ++cind;
62229371c9d4SSatish Balay             continue;
62239371c9d4SSatish Balay           }
622497e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
622597e99dd9SToby Isaac         }
622697e99dd9SToby Isaac       }
622797e99dd9SToby Isaac     } else {
622897e99dd9SToby Isaac       if (perm) {
622997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
62309371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62319371c9d4SSatish Balay             ++cind;
62329371c9d4SSatish Balay             continue;
62339371c9d4SSatish Balay           }
623497e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
623597e99dd9SToby Isaac         }
623697e99dd9SToby Isaac       } else {
623797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
62389371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62399371c9d4SSatish Balay             ++cind;
62409371c9d4SSatish Balay             continue;
62419371c9d4SSatish Balay           }
624297e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
624397e99dd9SToby Isaac         }
6244552f7358SJed Brown       }
6245552f7358SJed Brown     }
6246552f7358SJed Brown   }
62473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6248552f7358SJed Brown }
6249552f7358SJed Brown 
6250d71ae5a4SJacob 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[])
6251d71ae5a4SJacob Faibussowitsch {
6252a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6253a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6254a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6255a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6256a5e93ea8SMatthew G. Knepley 
6257a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
62589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
62599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6260a5e93ea8SMatthew G. Knepley   a = &array[off];
6261a5e93ea8SMatthew G. Knepley   if (cdof) {
62629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
626397e99dd9SToby Isaac     if (clperm) {
626497e99dd9SToby Isaac       if (perm) {
6265a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6266a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
626797e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
626897e99dd9SToby Isaac             cind++;
6269a5e93ea8SMatthew G. Knepley           }
6270a5e93ea8SMatthew G. Knepley         }
6271a5e93ea8SMatthew G. Knepley       } else {
6272a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6273a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
627497e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
627597e99dd9SToby Isaac             cind++;
627697e99dd9SToby Isaac           }
627797e99dd9SToby Isaac         }
627897e99dd9SToby Isaac       }
627997e99dd9SToby Isaac     } else {
628097e99dd9SToby Isaac       if (perm) {
628197e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
628297e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
628397e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
628497e99dd9SToby Isaac             cind++;
628597e99dd9SToby Isaac           }
628697e99dd9SToby Isaac         }
628797e99dd9SToby Isaac       } else {
628897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
628997e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
629097e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
629197e99dd9SToby Isaac             cind++;
629297e99dd9SToby Isaac           }
6293a5e93ea8SMatthew G. Knepley         }
6294a5e93ea8SMatthew G. Knepley       }
6295a5e93ea8SMatthew G. Knepley     }
6296a5e93ea8SMatthew G. Knepley   }
62973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6298a5e93ea8SMatthew G. Knepley }
6299a5e93ea8SMatthew G. Knepley 
6300d71ae5a4SJacob 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[])
6301d71ae5a4SJacob Faibussowitsch {
6302552f7358SJed Brown   PetscScalar    *a;
63031a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
63041a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
630597e99dd9SToby Isaac   PetscInt        cind = 0, b;
6306552f7358SJed Brown 
6307552f7358SJed Brown   PetscFunctionBegin;
63089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
63109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63111a271a75SMatthew G. Knepley   a = &array[foff];
6312552f7358SJed Brown   if (!fcdof || setBC) {
631397e99dd9SToby Isaac     if (clperm) {
63149371c9d4SSatish Balay       if (perm) {
6315ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6316552f7358SJed Brown       } else {
6317ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
63189371c9d4SSatish Balay       }
63199371c9d4SSatish Balay     } else {
63209371c9d4SSatish Balay       if (perm) {
6321ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
63229371c9d4SSatish Balay       } else {
6323ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
63249371c9d4SSatish Balay       }
6325552f7358SJed Brown     }
6326552f7358SJed Brown   } else {
63279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
632897e99dd9SToby Isaac     if (clperm) {
632997e99dd9SToby Isaac       if (perm) {
633097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63319371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63329371c9d4SSatish Balay             ++cind;
63339371c9d4SSatish Balay             continue;
63349371c9d4SSatish Balay           }
633597e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6336552f7358SJed Brown         }
6337552f7358SJed Brown       } else {
633897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63399371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63409371c9d4SSatish Balay             ++cind;
63419371c9d4SSatish Balay             continue;
63429371c9d4SSatish Balay           }
634397e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
634497e99dd9SToby Isaac         }
634597e99dd9SToby Isaac       }
634697e99dd9SToby Isaac     } else {
634797e99dd9SToby Isaac       if (perm) {
634897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63499371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63509371c9d4SSatish Balay             ++cind;
63519371c9d4SSatish Balay             continue;
63529371c9d4SSatish Balay           }
635397e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
635497e99dd9SToby Isaac         }
635597e99dd9SToby Isaac       } else {
635697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63579371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63589371c9d4SSatish Balay             ++cind;
63599371c9d4SSatish Balay             continue;
63609371c9d4SSatish Balay           }
636197e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6362552f7358SJed Brown         }
6363552f7358SJed Brown       }
6364552f7358SJed Brown     }
6365552f7358SJed Brown   }
63661a271a75SMatthew G. Knepley   *offset += fdof;
63673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6368552f7358SJed Brown }
6369552f7358SJed Brown 
6370d71ae5a4SJacob 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[])
6371d71ae5a4SJacob Faibussowitsch {
6372a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
63731a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
63741a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
63755da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6376ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6377a5e93ea8SMatthew G. Knepley 
6378a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
63799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
63809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
63829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63831a271a75SMatthew G. Knepley   a = &array[foff];
6384a5e93ea8SMatthew G. Knepley   if (fcdof) {
6385ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
63869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
638797e99dd9SToby Isaac     if (clperm) {
638897e99dd9SToby Isaac       if (perm) {
6389ba322698SMatthew G. Knepley         if (comps) {
6390ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6391ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
63929371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
63939371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
63949371c9d4SSatish Balay               ncSet = PETSC_TRUE;
63959371c9d4SSatish Balay             }
63969371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
63979371c9d4SSatish Balay               ++cind;
63989371c9d4SSatish Balay               fcSet = PETSC_TRUE;
63999371c9d4SSatish Balay             }
6400ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6401ba322698SMatthew G. Knepley           }
6402ba322698SMatthew G. Knepley         } else {
640397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
640497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
640597e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6406a5e93ea8SMatthew G. Knepley               ++cind;
6407a5e93ea8SMatthew G. Knepley             }
6408a5e93ea8SMatthew G. Knepley           }
6409ba322698SMatthew G. Knepley         }
6410ba322698SMatthew G. Knepley       } else {
6411ba322698SMatthew G. Knepley         if (comps) {
6412ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6413ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64149371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64159371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64169371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64179371c9d4SSatish Balay             }
64189371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64199371c9d4SSatish Balay               ++cind;
64209371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64219371c9d4SSatish Balay             }
6422ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6423ba322698SMatthew G. Knepley           }
6424a5e93ea8SMatthew G. Knepley         } else {
642597e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
642697e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
642797e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
642897e99dd9SToby Isaac               ++cind;
642997e99dd9SToby Isaac             }
643097e99dd9SToby Isaac           }
643197e99dd9SToby Isaac         }
6432ba322698SMatthew G. Knepley       }
643397e99dd9SToby Isaac     } else {
643497e99dd9SToby Isaac       if (perm) {
6435ba322698SMatthew G. Knepley         if (comps) {
6436ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6437ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64389371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64399371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64409371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64419371c9d4SSatish Balay             }
64429371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64439371c9d4SSatish Balay               ++cind;
64449371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64459371c9d4SSatish Balay             }
6446ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6447ba322698SMatthew G. Knepley           }
6448ba322698SMatthew G. Knepley         } else {
644997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
645097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
645197e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
645297e99dd9SToby Isaac               ++cind;
645397e99dd9SToby Isaac             }
645497e99dd9SToby Isaac           }
6455ba322698SMatthew G. Knepley         }
6456ba322698SMatthew G. Knepley       } else {
6457ba322698SMatthew G. Knepley         if (comps) {
6458ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6459ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64609371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64619371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64629371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64639371c9d4SSatish Balay             }
64649371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64659371c9d4SSatish Balay               ++cind;
64669371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64679371c9d4SSatish Balay             }
6468ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6469ba322698SMatthew G. Knepley           }
647097e99dd9SToby Isaac         } else {
647197e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
647297e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
647397e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6474a5e93ea8SMatthew G. Knepley               ++cind;
6475a5e93ea8SMatthew G. Knepley             }
6476a5e93ea8SMatthew G. Knepley           }
6477a5e93ea8SMatthew G. Knepley         }
6478a5e93ea8SMatthew G. Knepley       }
6479a5e93ea8SMatthew G. Knepley     }
6480ba322698SMatthew G. Knepley   }
64811a271a75SMatthew G. Knepley   *offset += fdof;
64823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6483a5e93ea8SMatthew G. Knepley }
6484a5e93ea8SMatthew G. Knepley 
6485d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6486d71ae5a4SJacob Faibussowitsch {
6487552f7358SJed Brown   PetscScalar    *array;
64881b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
64891b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6490552f7358SJed Brown 
64911b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
64929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
64939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
64949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
64959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
64969566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6497b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6498b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6499b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6500b6ebb6e6SMatthew G. Knepley 
65019371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
65029371c9d4SSatish Balay       dof = 0;
65039371c9d4SSatish Balay       continue;
65049371c9d4SSatish Balay     }
65059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6506b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6507b6ebb6e6SMatthew G. Knepley     {
6508b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6509b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6510b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6511b6ebb6e6SMatthew G. Knepley 
65129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
65139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6514b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6515b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6516b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6517ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6518b6ebb6e6SMatthew G. Knepley         } else {
6519ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6520b6ebb6e6SMatthew G. Knepley         }
6521b6ebb6e6SMatthew G. Knepley       } else {
65229566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6523b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6524b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
65259371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
65269371c9d4SSatish Balay               ++cind;
65279371c9d4SSatish Balay               continue;
65289371c9d4SSatish Balay             }
6529b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6530b6ebb6e6SMatthew G. Knepley           }
6531b6ebb6e6SMatthew G. Knepley         } else {
6532b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
65339371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
65349371c9d4SSatish Balay               ++cind;
65359371c9d4SSatish Balay               continue;
65369371c9d4SSatish Balay             }
6537b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6538b6ebb6e6SMatthew G. Knepley           }
6539b6ebb6e6SMatthew G. Knepley         }
6540b6ebb6e6SMatthew G. Knepley       }
6541b6ebb6e6SMatthew G. Knepley     }
6542b6ebb6e6SMatthew G. Knepley   }
65439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
65443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6545b6ebb6e6SMatthew G. Knepley }
65461b406b76SMatthew G. Knepley 
65471b406b76SMatthew G. Knepley /*@C
654820f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
65491b406b76SMatthew G. Knepley 
65501b406b76SMatthew G. Knepley   Not collective
65511b406b76SMatthew G. Knepley 
65521b406b76SMatthew G. Knepley   Input Parameters:
6553a1cb98faSBarry Smith + dm - The `DM`
655420f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
65551b406b76SMatthew G. Knepley . v - The local vector
655620f4b53cSBarry Smith . point - The point in the `DM`
65571b406b76SMatthew G. Knepley . values - The array of values
6558a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6559a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
65601b406b76SMatthew G. Knepley 
65611b406b76SMatthew G. Knepley   Level: intermediate
65621b406b76SMatthew G. Knepley 
65631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
65641b406b76SMatthew G. Knepley @*/
6565d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6566d71ae5a4SJacob Faibussowitsch {
65671b406b76SMatthew G. Knepley   PetscSection    clSection;
65681b406b76SMatthew G. Knepley   IS              clPoints;
65691b406b76SMatthew G. Knepley   PetscScalar    *array;
65701b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
657127f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6572c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
65731b406b76SMatthew G. Knepley 
65741a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
65751b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65769566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
65771a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
65781a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
65799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
65809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
65811b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
65829566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
65833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
65841b406b76SMatthew G. Knepley   }
65851a271a75SMatthew G. Knepley   /* Get points */
658607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6587c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6588c459fbc1SJed Brown     PetscInt dof;
65899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6590c459fbc1SJed Brown     clsize += dof;
6591c459fbc1SJed Brown   }
65929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
65931a271a75SMatthew G. Knepley   /* Get array */
65949566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
65951a271a75SMatthew G. Knepley   /* Get values */
6596ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
659797e99dd9SToby Isaac     PetscInt offset = 0, f;
6598552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
659997e99dd9SToby Isaac       const PetscInt    **perms = NULL;
660097e99dd9SToby Isaac       const PetscScalar **flips = NULL;
660197e99dd9SToby Isaac 
66029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6603552f7358SJed Brown       switch (mode) {
6604552f7358SJed Brown       case INSERT_VALUES:
660597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
660697e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
660797e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
660897e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66093ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
66109371c9d4SSatish Balay         }
66119371c9d4SSatish Balay         break;
6612552f7358SJed Brown       case INSERT_ALL_VALUES:
661397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
661497e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
661597e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
661697e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66173ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
66189371c9d4SSatish Balay         }
66199371c9d4SSatish Balay         break;
6620a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
662197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
662297e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
662397e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
662497e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66253ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
66269371c9d4SSatish Balay         }
66279371c9d4SSatish Balay         break;
6628552f7358SJed Brown       case ADD_VALUES:
662997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
663097e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
663197e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
663297e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66333ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
66349371c9d4SSatish Balay         }
66359371c9d4SSatish Balay         break;
6636552f7358SJed Brown       case ADD_ALL_VALUES:
663797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
663897e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
663997e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
664097e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66413ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
66429371c9d4SSatish Balay         }
66439371c9d4SSatish Balay         break;
6644304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
664597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
664697e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
664797e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
664897e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66493ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
66509371c9d4SSatish Balay         }
66519371c9d4SSatish Balay         break;
6652d71ae5a4SJacob Faibussowitsch       default:
6653d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6654552f7358SJed Brown       }
66559566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
66561a271a75SMatthew G. Knepley     }
6657552f7358SJed Brown   } else {
66581a271a75SMatthew G. Knepley     PetscInt            dof, off;
665997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
666097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
66611a271a75SMatthew G. Knepley 
66629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
6663552f7358SJed Brown     switch (mode) {
6664552f7358SJed Brown     case INSERT_VALUES:
666597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
666697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
666797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
666897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66699566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
66703ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
66719371c9d4SSatish Balay       }
66729371c9d4SSatish Balay       break;
6673552f7358SJed Brown     case INSERT_ALL_VALUES:
667497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
667597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
667697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
667797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
66793ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
66809371c9d4SSatish Balay       }
66819371c9d4SSatish Balay       break;
6682a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
668397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
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;
66879566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
66883ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
66899371c9d4SSatish Balay       }
66909371c9d4SSatish Balay       break;
6691552f7358SJed Brown     case ADD_VALUES:
669297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
669397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
669497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
669597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
66973ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
66989371c9d4SSatish Balay       }
66999371c9d4SSatish Balay       break;
6700552f7358SJed Brown     case ADD_ALL_VALUES:
670197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
670297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
670397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
670497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67063ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
67079371c9d4SSatish Balay       }
67089371c9d4SSatish Balay       break;
6709304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
671097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
671197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
671297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
671397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67149566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67153ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
67169371c9d4SSatish Balay       }
67179371c9d4SSatish Balay       break;
6718d71ae5a4SJacob Faibussowitsch     default:
6719d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6720552f7358SJed Brown     }
67219566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
6722552f7358SJed Brown   }
67231a271a75SMatthew G. Knepley   /* Cleanup points */
67249566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
67251a271a75SMatthew G. Knepley   /* Cleanup array */
67269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
67273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6728552f7358SJed Brown }
6729552f7358SJed Brown 
6730cfb853baSMatthew G. Knepley PetscErrorCode DMPlexVecSetStar(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6731cfb853baSMatthew G. Knepley {
6732cfb853baSMatthew G. Knepley   const PetscInt *supp, *cone;
6733cfb853baSMatthew G. Knepley   PetscScalar    *a;
6734cfb853baSMatthew G. Knepley   PetscInt        dim, Ns, dof, off, n = 0;
6735cfb853baSMatthew G. Knepley 
6736cfb853baSMatthew G. Knepley   PetscFunctionBegin;
6737cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6738cfb853baSMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6739cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6740cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
6741cfb853baSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) {
6742cfb853baSMatthew G. Knepley     PetscInt vStart, vEnd;
6743cfb853baSMatthew G. Knepley 
6744cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
6745cfb853baSMatthew 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);
6746cfb853baSMatthew G. Knepley   }
6747cfb853baSMatthew G. Knepley   PetscValidScalarPointer(values, 5);
6748cfb853baSMatthew G. Knepley 
6749cfb853baSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
6750cfb853baSMatthew G. Knepley   PetscCall(DMPlexGetSupportSize(dm, point, &Ns));
6751cfb853baSMatthew G. Knepley   PetscCall(DMPlexGetSupport(dm, point, &supp));
6752cfb853baSMatthew 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);
6753cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(v, &a));
6754cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetDof(section, point, &dof));
6755cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetOffset(section, point, &off));
6756cfb853baSMatthew G. Knepley   for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6757cfb853baSMatthew G. Knepley   for (PetscInt d = 0; d < dim; ++d) {
6758cfb853baSMatthew G. Knepley     // Left edge
6759cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetCone(dm, supp[2 * d + 0], &cone));
6760cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, cone[0], &dof));
6761cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(section, cone[0], &off));
6762cfb853baSMatthew G. Knepley     for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6763cfb853baSMatthew G. Knepley     // Right edge
6764cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetCone(dm, supp[2 * d + 1], &cone));
6765cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, cone[1], &dof));
6766cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(section, cone[1], &off));
6767cfb853baSMatthew G. Knepley     for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6768cfb853baSMatthew G. Knepley   }
6769cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(v, &a));
67703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6771cfb853baSMatthew G. Knepley }
6772cfb853baSMatthew G. Knepley 
67735f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
6774d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
6775d71ae5a4SJacob Faibussowitsch {
67765f790a90SMatthew G. Knepley   PetscFunctionBegin;
677711cc89d2SBarry Smith   *contains = PETSC_TRUE;
67785f790a90SMatthew G. Knepley   if (label) {
6779d6177c40SToby Isaac     PetscInt fdof;
67805f790a90SMatthew G. Knepley 
678111cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
678211cc89d2SBarry Smith     if (!*contains) {
67839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67845f790a90SMatthew G. Knepley       *offset += fdof;
67853ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
67865f790a90SMatthew G. Knepley     }
67875f790a90SMatthew G. Knepley   }
67883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67895f790a90SMatthew G. Knepley }
67905f790a90SMatthew G. Knepley 
679197529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
6792d71ae5a4SJacob 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)
6793d71ae5a4SJacob Faibussowitsch {
6794e07394fbSMatthew G. Knepley   PetscSection    clSection;
6795e07394fbSMatthew G. Knepley   IS              clPoints;
6796e07394fbSMatthew G. Knepley   PetscScalar    *array;
6797e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
679897529cf3SJed Brown   const PetscInt *clp;
6799e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
680097e99dd9SToby Isaac   PetscInt        offset = 0, f;
6801e07394fbSMatthew G. Knepley 
6802e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6803e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68049566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6805e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6806e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
68079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6808e07394fbSMatthew G. Knepley   /* Get points */
680907218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6810e07394fbSMatthew G. Knepley   /* Get array */
68119566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6812e07394fbSMatthew G. Knepley   /* Get values */
6813e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
681497e99dd9SToby Isaac     const PetscInt    **perms = NULL;
681597e99dd9SToby Isaac     const PetscScalar **flips = NULL;
681611cc89d2SBarry Smith     PetscBool           contains;
681797e99dd9SToby Isaac 
6818e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6819e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
6820e07394fbSMatthew G. Knepley         PetscInt fdof;
68219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6822e07394fbSMatthew G. Knepley         offset += fdof;
6823e07394fbSMatthew G. Knepley       }
6824e07394fbSMatthew G. Knepley       continue;
6825e07394fbSMatthew G. Knepley     }
68269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6827e07394fbSMatthew G. Knepley     switch (mode) {
6828e07394fbSMatthew G. Knepley     case INSERT_VALUES:
682997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
683097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
683197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
683297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
683311cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
683411cc89d2SBarry Smith         if (!contains) continue;
68359566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
68369371c9d4SSatish Balay       }
68379371c9d4SSatish Balay       break;
6838e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
683997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
684097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
684197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
684297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
684311cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
684411cc89d2SBarry Smith         if (!contains) continue;
68459566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
68469371c9d4SSatish Balay       }
68479371c9d4SSatish Balay       break;
6848e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
684997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
685097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
685197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
685297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
685311cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
685411cc89d2SBarry Smith         if (!contains) continue;
68559566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
68569371c9d4SSatish Balay       }
68579371c9d4SSatish Balay       break;
6858e07394fbSMatthew G. Knepley     case ADD_VALUES:
685997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
686097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
686197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
686297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
686311cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
686411cc89d2SBarry Smith         if (!contains) continue;
68659566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
68669371c9d4SSatish Balay       }
68679371c9d4SSatish Balay       break;
6868e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
686997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
687097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
687197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
687297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
687311cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
687411cc89d2SBarry Smith         if (!contains) continue;
68759566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
68769371c9d4SSatish Balay       }
68779371c9d4SSatish Balay       break;
6878d71ae5a4SJacob Faibussowitsch     default:
6879d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6880e07394fbSMatthew G. Knepley     }
68819566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6882e07394fbSMatthew G. Knepley   }
6883e07394fbSMatthew G. Knepley   /* Cleanup points */
68849566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6885e07394fbSMatthew G. Knepley   /* Cleanup array */
68869566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
68873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6888e07394fbSMatthew G. Knepley }
6889e07394fbSMatthew G. Knepley 
6890d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6891d71ae5a4SJacob Faibussowitsch {
6892552f7358SJed Brown   PetscMPIInt rank;
6893552f7358SJed Brown   PetscInt    i, j;
6894552f7358SJed Brown 
6895552f7358SJed Brown   PetscFunctionBegin;
68969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
689763a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
689863a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
689963a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6900b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
69013ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
6902b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
69039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6904b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6905519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
69069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
6907552f7358SJed Brown #else
69089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
6909552f7358SJed Brown #endif
6910552f7358SJed Brown     }
69119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6912552f7358SJed Brown   }
69133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6914552f7358SJed Brown }
6915552f7358SJed Brown 
691605586334SMatthew G. Knepley /*
691705586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
691805586334SMatthew G. Knepley 
691905586334SMatthew G. Knepley   Input Parameters:
692005586334SMatthew G. Knepley + section - The section for this data layout
692136fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
692205586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
692305586334SMatthew G. Knepley . off     - The global offset of this point
692405586334SMatthew G. Knepley . loff    - The local offset of each field
6925a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
692605586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
692705586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
692805586334SMatthew G. Knepley 
692905586334SMatthew G. Knepley   Output Parameter:
693005586334SMatthew G. Knepley . indices - Indices for dofs on this point
693105586334SMatthew G. Knepley 
693205586334SMatthew G. Knepley   Level: developer
693305586334SMatthew G. Knepley 
693405586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
693505586334SMatthew G. Knepley */
6936d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6937d71ae5a4SJacob Faibussowitsch {
6938e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6939552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6940552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6941552f7358SJed Brown   PetscInt        cind = 0, k;
6942552f7358SJed Brown 
6943552f7358SJed Brown   PetscFunctionBegin;
694408401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
69459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
69469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6947552f7358SJed Brown   if (!cdof || setBC) {
694805586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
694905586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
695005586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
695105586334SMatthew G. Knepley 
695205586334SMatthew G. Knepley       indices[ind] = off + k;
6953552f7358SJed Brown     }
6954552f7358SJed Brown   } else {
69559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
69564acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
695705586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
695805586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
695905586334SMatthew G. Knepley 
69604acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
69614acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
696205586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
69634acb8e1eSToby Isaac         ++cind;
69644acb8e1eSToby Isaac       } else {
696536fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6966552f7358SJed Brown       }
6967552f7358SJed Brown     }
6968552f7358SJed Brown   }
6969e6ccafaeSMatthew G Knepley   *loff += dof;
69703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6971552f7358SJed Brown }
6972552f7358SJed Brown 
69737e29afd2SMatthew G. Knepley /*
697436fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
69757e29afd2SMatthew G. Knepley 
697636fa2b79SJed Brown  Input Parameters:
697736fa2b79SJed Brown + section - a section (global or local)
697820f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
697936fa2b79SJed Brown . point - point within section
698036fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
698136fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
698236fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
698336fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
698436fa2b79SJed Brown . permsoff - offset
698536fa2b79SJed Brown - indperm - index permutation
698636fa2b79SJed Brown 
698736fa2b79SJed Brown  Output Parameter:
698836fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
698936fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
699036fa2b79SJed Brown 
699136fa2b79SJed Brown  Notes:
699236fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
699336fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
699436fa2b79SJed Brown  in the local vector.
699536fa2b79SJed Brown 
699636fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
699736fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
699836fa2b79SJed Brown 
699936fa2b79SJed Brown  Developer Note:
700036fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
700136fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
700236fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
700336fa2b79SJed Brown 
700436fa2b79SJed Brown  Example:
700536fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
700636fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
700736fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
700836fa2b79SJed 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.
700936fa2b79SJed Brown 
701036fa2b79SJed Brown  Level: developer
70117e29afd2SMatthew G. Knepley */
7012d71ae5a4SJacob 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[])
7013d71ae5a4SJacob Faibussowitsch {
7014552f7358SJed Brown   PetscInt numFields, foff, f;
7015552f7358SJed Brown 
7016552f7358SJed Brown   PetscFunctionBegin;
701708401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
70189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7019552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
70204acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7021552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
70224acb8e1eSToby Isaac     PetscInt        cind = 0, b;
70234acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7024552f7358SJed Brown 
70259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7027552f7358SJed Brown     if (!cfdof || setBC) {
702805586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
702905586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
703005586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
703105586334SMatthew G. Knepley 
703205586334SMatthew G. Knepley         indices[ind] = off + foff + b;
703305586334SMatthew G. Knepley       }
7034552f7358SJed Brown     } else {
70359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
703605586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
703705586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
703805586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
703905586334SMatthew G. Knepley 
70404acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
704105586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7042552f7358SJed Brown           ++cind;
7043552f7358SJed Brown         } else {
704436fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7045552f7358SJed Brown         }
7046552f7358SJed Brown       }
7047552f7358SJed Brown     }
704836fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7049552f7358SJed Brown     foffs[f] += fdof;
7050552f7358SJed Brown   }
70513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7052552f7358SJed Brown }
7053552f7358SJed Brown 
70547e29afd2SMatthew G. Knepley /*
70557e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
70567e29afd2SMatthew G. Knepley 
70577e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7058645102dcSJed Brown 
7059645102dcSJed Brown  Notes:
7060645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7061645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
70627e29afd2SMatthew G. Knepley */
7063d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7064d71ae5a4SJacob Faibussowitsch {
70657e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
70667e29afd2SMatthew G. Knepley 
70677e29afd2SMatthew G. Knepley   PetscFunctionBegin;
70689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
70697e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
70707e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
70717e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
70727e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
70737e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
70747e29afd2SMatthew G. Knepley 
70759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
70779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7078645102dcSJed Brown     if (!cfdof) {
707905586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
708005586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
708105586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
708205586334SMatthew G. Knepley 
708305586334SMatthew G. Knepley         indices[ind] = foff + b;
708405586334SMatthew G. Knepley       }
70857e29afd2SMatthew G. Knepley     } else {
70869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
708705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
708805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
708905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
709005586334SMatthew G. Knepley 
70917e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
709205586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
70937e29afd2SMatthew G. Knepley           ++cind;
70947e29afd2SMatthew G. Knepley         } else {
709505586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
70967e29afd2SMatthew G. Knepley         }
70977e29afd2SMatthew G. Knepley       }
70987e29afd2SMatthew G. Knepley     }
70997e29afd2SMatthew G. Knepley     foffs[f] += fdof;
71007e29afd2SMatthew G. Knepley   }
71013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71027e29afd2SMatthew G. Knepley }
71037e29afd2SMatthew G. Knepley 
7104d71ae5a4SJacob 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)
7105d71ae5a4SJacob Faibussowitsch {
7106d3d1a6afSToby Isaac   Mat             cMat;
7107d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7108d3d1a6afSToby Isaac   IS              aIS;
7109d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7110d3d1a6afSToby Isaac   const PetscInt *anchors;
7111e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7112d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7113d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7114d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7115d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7116d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7117d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7118d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
71196ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7120d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7121d3d1a6afSToby Isaac 
7122d3d1a6afSToby Isaac   PetscFunctionBegin;
7123d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7124d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
71259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7126d3d1a6afSToby Isaac 
71279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7128d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7129d3d1a6afSToby Isaac   if (aSec) {
71309566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
71319566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
71329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7133d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7134d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7135d3d1a6afSToby Isaac      * into the global matrix anyway) */
7136d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7137d3d1a6afSToby Isaac       PetscInt b    = points[p];
71384b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7139d3d1a6afSToby Isaac 
71409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7141ad540459SPierre Jolivet       if (!bSecDof) continue;
714248a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7143d3d1a6afSToby Isaac       if (bDof) {
7144d3d1a6afSToby Isaac         /* this point is constrained */
7145d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7146d3d1a6afSToby Isaac         PetscInt bOff, q;
7147d3d1a6afSToby Isaac 
7148d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7149d3d1a6afSToby Isaac         newNumPoints += bDof;
71509566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7151d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7152d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7153d3d1a6afSToby Isaac           PetscInt aDof;
7154d3d1a6afSToby Isaac 
71559566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7156d3d1a6afSToby Isaac           newNumIndices += aDof;
7157d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7158d3d1a6afSToby Isaac             PetscInt fDof;
7159d3d1a6afSToby Isaac 
71609566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7161d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7162d3d1a6afSToby Isaac           }
7163d3d1a6afSToby Isaac         }
71649371c9d4SSatish Balay       } else {
7165d3d1a6afSToby Isaac         /* this point is not constrained */
7166d3d1a6afSToby Isaac         newNumPoints++;
71674b2f2278SToby Isaac         newNumIndices += bSecDof;
7168d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7169d3d1a6afSToby Isaac           PetscInt fDof;
7170d3d1a6afSToby Isaac 
71719566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7172d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7173d3d1a6afSToby Isaac         }
7174d3d1a6afSToby Isaac       }
7175d3d1a6afSToby Isaac     }
7176d3d1a6afSToby Isaac   }
7177d3d1a6afSToby Isaac   if (!anyConstrained) {
717872b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
717972b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
718072b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
718172b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
71829566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
71833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7184d3d1a6afSToby Isaac   }
7185d3d1a6afSToby Isaac 
71866ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
71876ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
71886ecaa68aSToby Isaac 
7189f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7190d3d1a6afSToby Isaac 
71916ecaa68aSToby Isaac   if (!outPoints && !outValues) {
71926ecaa68aSToby Isaac     if (offsets) {
7193ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
71946ecaa68aSToby Isaac     }
71959566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
71963ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
71976ecaa68aSToby Isaac   }
71986ecaa68aSToby Isaac 
71991dca8a05SBarry 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);
7200d3d1a6afSToby Isaac 
72019566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7202d3d1a6afSToby Isaac 
7203d3d1a6afSToby Isaac   /* workspaces */
7204d3d1a6afSToby Isaac   if (numFields) {
7205d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72069566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
72079566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7208d3d1a6afSToby Isaac     }
72099371c9d4SSatish Balay   } else {
72109566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
72119566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7212d3d1a6afSToby Isaac   }
7213d3d1a6afSToby Isaac 
7214d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7215d3d1a6afSToby Isaac   if (numFields) {
72164b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
72174b2f2278SToby Isaac 
7218d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7219d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
72204b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7221d3d1a6afSToby Isaac 
72229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
72234b2f2278SToby Isaac       if (!bSecDof) {
72244b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
72254b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
72264b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
72274b2f2278SToby Isaac         }
72284b2f2278SToby Isaac         continue;
72294b2f2278SToby Isaac       }
723048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7231d3d1a6afSToby Isaac       if (bDof) {
7232d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7233d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7234d3d1a6afSToby Isaac 
72359566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
72369566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7237d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7238d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7239d3d1a6afSToby Isaac             PetscInt aFDof;
7240d3d1a6afSToby Isaac 
72419566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7242d3d1a6afSToby Isaac             allFDof += aFDof;
7243d3d1a6afSToby Isaac           }
7244d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7245d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7246d3d1a6afSToby Isaac         }
72479371c9d4SSatish Balay       } else {
7248d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7249d3d1a6afSToby Isaac           PetscInt fDof;
7250d3d1a6afSToby Isaac 
72519566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7252d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7253d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7254d3d1a6afSToby Isaac         }
7255d3d1a6afSToby Isaac       }
7256d3d1a6afSToby Isaac     }
72574b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
72584b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
72594b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7260d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7261d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7262d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7263d3d1a6afSToby Isaac       }
726419f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
726519f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
72669566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7267d3d1a6afSToby Isaac     }
72689371c9d4SSatish Balay   } else {
7269d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7270d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
72714b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7272d3d1a6afSToby Isaac 
72739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
72744b2f2278SToby Isaac       if (!bSecDof) {
72754b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
72764b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
72774b2f2278SToby Isaac         continue;
72784b2f2278SToby Isaac       }
727948a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7280d3d1a6afSToby Isaac       if (bDof) {
72814b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7282d3d1a6afSToby Isaac 
72839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7284d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7285d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7286d3d1a6afSToby Isaac 
72879566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7288d3d1a6afSToby Isaac           allDof += aDof;
7289d3d1a6afSToby Isaac         }
7290d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
72914b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
72929371c9d4SSatish Balay       } else {
72934b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7294d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7295d3d1a6afSToby Isaac       }
7296d3d1a6afSToby Isaac     }
7297d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7298d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7299d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7300d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7301d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7302d3d1a6afSToby Isaac     }
73039566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7304d3d1a6afSToby Isaac   }
7305d3d1a6afSToby Isaac 
73066ecaa68aSToby Isaac   /* output arrays */
73079566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
73086ecaa68aSToby Isaac 
7309d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
73109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
73119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
73129566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
73139566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7314d3d1a6afSToby Isaac   if (numFields) {
7315d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7316d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7317d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
73184b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7319d3d1a6afSToby Isaac 
73209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7321ad540459SPierre Jolivet       if (!bSecDof) continue;
732248a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7323d3d1a6afSToby Isaac       if (bDof) {
7324d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7325d3d1a6afSToby Isaac 
7326d3d1a6afSToby Isaac         fStart[0] = 0;
7327d3d1a6afSToby Isaac         fEnd[0]   = 0;
7328d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7329d3d1a6afSToby Isaac           PetscInt fDof;
7330d3d1a6afSToby Isaac 
73319566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7332d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7333d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7334d3d1a6afSToby Isaac         }
73359566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
73369566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7337d3d1a6afSToby Isaac 
7338d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7339d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7340d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7341d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7342d3d1a6afSToby Isaac 
7343d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7344d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7345d3d1a6afSToby Isaac         }
73469566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7347d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7348d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7349d3d1a6afSToby Isaac 
7350d3d1a6afSToby 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 */
7351d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7352d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
73539566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
73549566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7355d3d1a6afSToby Isaac         }
7356d3d1a6afSToby Isaac         newP += bDof;
7357d3d1a6afSToby Isaac 
73586ecaa68aSToby Isaac         if (outValues) {
7359d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
736048a46eb9SPierre 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]));
7361d3d1a6afSToby Isaac         }
73629371c9d4SSatish Balay       } else {
7363d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7364d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7365d3d1a6afSToby Isaac         newP++;
7366d3d1a6afSToby Isaac       }
7367d3d1a6afSToby Isaac     }
7368d3d1a6afSToby Isaac   } else {
7369d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7370d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7371d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
73724b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7373d3d1a6afSToby Isaac 
73749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7375ad540459SPierre Jolivet       if (!bSecDof) continue;
737648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7377d3d1a6afSToby Isaac       if (bDof) {
7378d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7379d3d1a6afSToby Isaac 
73809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
73819566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7382d3d1a6afSToby Isaac 
73839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7384d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7385d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7386d3d1a6afSToby Isaac 
7387d3d1a6afSToby 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 */
7388d3d1a6afSToby Isaac 
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(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7393d3d1a6afSToby Isaac         }
7394d3d1a6afSToby Isaac         newP += bDof;
7395d3d1a6afSToby Isaac 
7396d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
739748a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
73989371c9d4SSatish Balay       } else {
7399d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7400d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7401d3d1a6afSToby Isaac         newP++;
7402d3d1a6afSToby Isaac       }
7403d3d1a6afSToby Isaac     }
7404d3d1a6afSToby Isaac   }
7405d3d1a6afSToby Isaac 
74066ecaa68aSToby Isaac   if (outValues) {
74079566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
74089566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7409d3d1a6afSToby Isaac     /* multiply constraints on the right */
7410d3d1a6afSToby Isaac     if (numFields) {
7411d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7412d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7413d3d1a6afSToby Isaac 
7414d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7415d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7416d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7417d3d1a6afSToby Isaac           PetscInt c, r, k;
7418d3d1a6afSToby Isaac           PetscInt dof;
7419d3d1a6afSToby Isaac 
74209566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7421ad540459SPierre Jolivet           if (!dof) continue;
7422d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7423d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7424d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7425d3d1a6afSToby Isaac 
7426d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7427d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7428ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7429d3d1a6afSToby Isaac               }
7430d3d1a6afSToby Isaac             }
74319371c9d4SSatish Balay           } else {
7432d3d1a6afSToby Isaac             /* copy this column as is */
7433d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7434ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7435d3d1a6afSToby Isaac             }
7436d3d1a6afSToby Isaac           }
7437d3d1a6afSToby Isaac           oldOff += dof;
7438d3d1a6afSToby Isaac         }
7439d3d1a6afSToby Isaac       }
74409371c9d4SSatish Balay     } else {
7441d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7442d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7443d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7444d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7445d3d1a6afSToby Isaac         PetscInt c, r, k;
7446d3d1a6afSToby Isaac         PetscInt dof;
7447d3d1a6afSToby Isaac 
74489566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7449ad540459SPierre Jolivet         if (!dof) continue;
7450d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7451d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7452d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7453d3d1a6afSToby Isaac 
7454d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7455d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7456ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7457d3d1a6afSToby Isaac             }
7458d3d1a6afSToby Isaac           }
74599371c9d4SSatish Balay         } else {
7460d3d1a6afSToby Isaac           /* copy this column as is */
7461d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7462ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7463d3d1a6afSToby Isaac           }
7464d3d1a6afSToby Isaac         }
7465d3d1a6afSToby Isaac         oldOff += dof;
7466d3d1a6afSToby Isaac       }
7467d3d1a6afSToby Isaac     }
7468d3d1a6afSToby Isaac 
74696ecaa68aSToby Isaac     if (multiplyLeft) {
74709566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
74719566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7472d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7473d3d1a6afSToby Isaac       if (numFields) {
7474d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7475d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7476d3d1a6afSToby Isaac 
7477d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7478d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7479d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7480d3d1a6afSToby Isaac             PetscInt c, r, k;
7481d3d1a6afSToby Isaac             PetscInt dof;
7482d3d1a6afSToby Isaac 
74839566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7484d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7485d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7486d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7487d3d1a6afSToby Isaac 
7488d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7489d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7490ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7491d3d1a6afSToby Isaac                 }
7492d3d1a6afSToby Isaac               }
74939371c9d4SSatish Balay             } else {
7494d3d1a6afSToby Isaac               /* copy this row as is */
7495d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7496ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7497d3d1a6afSToby Isaac               }
7498d3d1a6afSToby Isaac             }
7499d3d1a6afSToby Isaac             oldOff += dof;
7500d3d1a6afSToby Isaac           }
7501d3d1a6afSToby Isaac         }
75029371c9d4SSatish Balay       } else {
7503d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7504d3d1a6afSToby Isaac 
7505d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7506d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7507d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7508d3d1a6afSToby Isaac           PetscInt c, r, k;
7509d3d1a6afSToby Isaac           PetscInt dof;
7510d3d1a6afSToby Isaac 
75119566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7512d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7513d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7514d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7515d3d1a6afSToby Isaac 
7516d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7517d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7518ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7519d3d1a6afSToby Isaac               }
7520d3d1a6afSToby Isaac             }
75219371c9d4SSatish Balay           } else {
7522d3d1a6afSToby Isaac             /* copy this row as is */
75239fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7524ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7525d3d1a6afSToby Isaac             }
7526d3d1a6afSToby Isaac           }
7527d3d1a6afSToby Isaac           oldOff += dof;
7528d3d1a6afSToby Isaac         }
7529d3d1a6afSToby Isaac       }
7530d3d1a6afSToby Isaac 
75319566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
75329371c9d4SSatish Balay     } else {
75336ecaa68aSToby Isaac       newValues = tmpValues;
75346ecaa68aSToby Isaac     }
75356ecaa68aSToby Isaac   }
75366ecaa68aSToby Isaac 
7537d3d1a6afSToby Isaac   /* clean up */
75389566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
75399566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
75406ecaa68aSToby Isaac 
7541d3d1a6afSToby Isaac   if (numFields) {
7542d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
75439566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
75449566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
75459566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7546d3d1a6afSToby Isaac     }
75479371c9d4SSatish Balay   } else {
75489566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
75499566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
75509566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7551d3d1a6afSToby Isaac   }
75529566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7553d3d1a6afSToby Isaac 
7554d3d1a6afSToby Isaac   /* output */
75556ecaa68aSToby Isaac   if (outPoints) {
7556d3d1a6afSToby Isaac     *outPoints = newPoints;
75579371c9d4SSatish Balay   } else {
75589566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
75596ecaa68aSToby Isaac   }
7560ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7561ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
75623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7563d3d1a6afSToby Isaac }
7564d3d1a6afSToby Isaac 
75654a1e0b3eSMatthew G. Knepley /*@C
756671f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
75677cd05799SMatthew G. Knepley 
75687cd05799SMatthew G. Knepley   Not collective
75697cd05799SMatthew G. Knepley 
75707cd05799SMatthew G. Knepley   Input Parameters:
7571a1cb98faSBarry Smith + dm         - The `DM`
7572a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7573a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
757471f0bbf9SMatthew G. Knepley . point      - The point defining the closure
757571f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
75767cd05799SMatthew G. Knepley 
757771f0bbf9SMatthew G. Knepley   Output Parameters:
757871f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
757971f0bbf9SMatthew G. Knepley . indices    - The dof indices
758020f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
758120f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
75827cd05799SMatthew G. Knepley 
7583a1cb98faSBarry Smith   Level: advanced
758436fa2b79SJed Brown 
7585a1cb98faSBarry Smith   Notes:
7586a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7587a1cb98faSBarry Smith 
758820f4b53cSBarry Smith   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
758920f4b53cSBarry Smith   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
759036fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
759120f4b53cSBarry Smith   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
759236fa2b79SJed Brown   indices (with the above semantics) are implied.
75937cd05799SMatthew G. Knepley 
75941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7595a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
75964a1e0b3eSMatthew G. Knepley @*/
7597d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7598d71ae5a4SJacob Faibussowitsch {
759971f0bbf9SMatthew G. Knepley   /* Closure ordering */
76007773e69fSMatthew G. Knepley   PetscSection    clSection;
76017773e69fSMatthew G. Knepley   IS              clPoints;
760271f0bbf9SMatthew G. Knepley   const PetscInt *clp;
760371f0bbf9SMatthew G. Knepley   PetscInt       *points;
760471f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
760571f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
76064acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
760771f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
760871f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
760971f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
761071f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
761171f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
761271f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
761371f0bbf9SMatthew G. Knepley 
761471f0bbf9SMatthew G. Knepley   PetscInt *idx;
761571f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
761671f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
76177773e69fSMatthew G. Knepley 
761871f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
76197773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
76207773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
762136fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7622dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
762371f0bbf9SMatthew G. Knepley   if (indices) PetscValidPointer(indices, 7);
7624dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
762571f0bbf9SMatthew G. Knepley   if (values) PetscValidPointer(values, 9);
76269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
762763a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
76289566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
762971f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
763007218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7631c459fbc1SJed Brown   if (useClPerm) {
7632c459fbc1SJed Brown     PetscInt depth, clsize;
76339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7634c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7635c459fbc1SJed Brown       PetscInt dof;
76369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7637c459fbc1SJed Brown       clsize += dof;
7638c459fbc1SJed Brown     }
76399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7640c459fbc1SJed Brown   }
764171f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
764271f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
76437773e69fSMatthew G. Knepley     PetscInt dof, fdof;
76447773e69fSMatthew G. Knepley 
76459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
76467773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
76479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
76487773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
76497773e69fSMatthew G. Knepley     }
765071f0bbf9SMatthew G. Knepley     Ni += dof;
76517773e69fSMatthew G. Knepley   }
76527773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
76531dca8a05SBarry 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);
765471f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
765571f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
76569566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
76579566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
765871f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
765971f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
766071f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
76616ecaa68aSToby Isaac 
766271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
766371f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
766471f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
766571f0bbf9SMatthew G. Knepley 
76669566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
76679566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
766871f0bbf9SMatthew G. Knepley         if (flip) {
766971f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
767071f0bbf9SMatthew G. Knepley 
767171f0bbf9SMatthew G. Knepley           if (!valCopy) {
76729566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
767371f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
767471f0bbf9SMatthew G. Knepley             *values = valCopy;
767571f0bbf9SMatthew G. Knepley           }
767671f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
767771f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
767871f0bbf9SMatthew G. Knepley 
767971f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
768071f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
768171f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
76826ecaa68aSToby Isaac             }
76836ecaa68aSToby Isaac           }
768471f0bbf9SMatthew G. Knepley         }
768571f0bbf9SMatthew G. Knepley         foffset += fdof;
768671f0bbf9SMatthew G. Knepley       }
768771f0bbf9SMatthew G. Knepley     }
768871f0bbf9SMatthew G. Knepley   }
768971f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
76909566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
769171f0bbf9SMatthew G. Knepley   if (NclC) {
76929566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
769371f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
76949566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
76959566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
769671f0bbf9SMatthew G. Knepley     }
769771f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
76989566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
76999566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
770071f0bbf9SMatthew G. Knepley     }
77019566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
770271f0bbf9SMatthew G. Knepley     Ncl    = NclC;
770371f0bbf9SMatthew G. Knepley     Ni     = NiC;
770471f0bbf9SMatthew G. Knepley     points = pointsC;
770571f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
770671f0bbf9SMatthew G. Knepley   }
770771f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
77089566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
770971f0bbf9SMatthew G. Knepley   if (Nf) {
771071f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
771171f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
771271f0bbf9SMatthew G. Knepley 
77139371c9d4SSatish Balay     if (outOffsets) {
77149371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
77159371c9d4SSatish Balay     }
77169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
771771f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
771871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
771971f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
772071f0bbf9SMatthew G. Knepley 
77219566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
77227773e69fSMatthew G. Knepley       }
77237773e69fSMatthew G. Knepley     } else {
772471f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
772571f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
772671f0bbf9SMatthew G. Knepley 
77279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
772871f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
772971f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
773071f0bbf9SMatthew G. Knepley          * global section. */
77319566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
773271f0bbf9SMatthew G. Knepley       }
773371f0bbf9SMatthew G. Knepley     }
773471f0bbf9SMatthew G. Knepley   } else {
773571f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
773671f0bbf9SMatthew G. Knepley 
773771f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
773871f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
77394acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
77404acb8e1eSToby Isaac 
77419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
774271f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
774371f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
77449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
77457773e69fSMatthew G. Knepley     }
77467773e69fSMatthew G. Knepley   }
774771f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
774871f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
77499566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
77509566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
77514acb8e1eSToby Isaac   }
775271f0bbf9SMatthew G. Knepley   if (NclC) {
77539566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
77547773e69fSMatthew G. Knepley   } else {
77559566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
77567773e69fSMatthew G. Knepley   }
775771f0bbf9SMatthew G. Knepley 
775871f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
775971f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
77603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77617773e69fSMatthew G. Knepley }
77627773e69fSMatthew G. Knepley 
77637cd05799SMatthew G. Knepley /*@C
776471f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
77657cd05799SMatthew G. Knepley 
77667cd05799SMatthew G. Knepley   Not collective
77677cd05799SMatthew G. Knepley 
77687cd05799SMatthew G. Knepley   Input Parameters:
7769a1cb98faSBarry Smith + dm         - The `DM`
7770a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7771a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
777271f0bbf9SMatthew G. Knepley . point      - The point defining the closure
777371f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
777471f0bbf9SMatthew G. Knepley 
777571f0bbf9SMatthew G. Knepley   Output Parameters:
777671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
777771f0bbf9SMatthew G. Knepley . indices    - The dof indices
777820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
777920f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
778071f0bbf9SMatthew G. Knepley 
7781a1cb98faSBarry Smith   Level: advanced
778271f0bbf9SMatthew G. Knepley 
7783a1cb98faSBarry Smith   Notes:
7784a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
7785a1cb98faSBarry Smith 
7786a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
778771f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
778871f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
778971f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
779071f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
77917cd05799SMatthew G. Knepley 
77921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
77937cd05799SMatthew G. Knepley @*/
7794d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7795d71ae5a4SJacob Faibussowitsch {
77967773e69fSMatthew G. Knepley   PetscFunctionBegin;
77977773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7798064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
77999566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
78003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78017773e69fSMatthew G. Knepley }
78027773e69fSMatthew G. Knepley 
78037f5d1fdeSMatthew G. Knepley /*@C
78047f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
78057f5d1fdeSMatthew G. Knepley 
78067f5d1fdeSMatthew G. Knepley   Not collective
78077f5d1fdeSMatthew G. Knepley 
78087f5d1fdeSMatthew G. Knepley   Input Parameters:
7809a1cb98faSBarry Smith + dm - The `DM`
781020f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
781120f4b53cSBarry Smith . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
78127f5d1fdeSMatthew G. Knepley . A - The matrix
7813a1cb98faSBarry Smith . point - The point in the `DM`
78147f5d1fdeSMatthew G. Knepley . values - The array of values
7815a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
78167f5d1fdeSMatthew G. Knepley 
78177f5d1fdeSMatthew G. Knepley   Level: intermediate
78187f5d1fdeSMatthew G. Knepley 
78191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
78207f5d1fdeSMatthew G. Knepley @*/
7821d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7822d71ae5a4SJacob Faibussowitsch {
7823552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
7824552f7358SJed Brown   PetscInt          *indices;
782571f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
782671f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7827552f7358SJed Brown   PetscErrorCode     ierr;
7828552f7358SJed Brown 
7829552f7358SJed Brown   PetscFunctionBegin;
7830552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78319566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
78323dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
78339566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
78343dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
78353dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7836552f7358SJed Brown 
78379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78380d644c17SKarl Rupp 
78399566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7840d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
78414a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7842552f7358SJed Brown   if (ierr) {
7843552f7358SJed Brown     PetscMPIInt rank;
7844552f7358SJed Brown 
78459566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
78469566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
78479566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
78489566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78499566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7850c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
7851552f7358SJed Brown   }
78524a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
78534a1e0b3eSMatthew G. Knepley     PetscInt i;
78549566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
785563a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
78569566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
78574a1e0b3eSMatthew G. Knepley   }
785871f0bbf9SMatthew G. Knepley 
78599566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78609566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
78613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78624acb8e1eSToby Isaac }
786371f0bbf9SMatthew G. Knepley 
78644a1e0b3eSMatthew G. Knepley /*@C
78654a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
78664a1e0b3eSMatthew G. Knepley 
78674a1e0b3eSMatthew G. Knepley   Not collective
78684a1e0b3eSMatthew G. Knepley 
78694a1e0b3eSMatthew G. Knepley   Input Parameters:
7870a1cb98faSBarry Smith + dmRow - The `DM` for the row fields
787120f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow`
787220f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
7873a1cb98faSBarry Smith . dmCol - The `DM` for the column fields
787420f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol`
787520f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
78764a1e0b3eSMatthew G. Knepley . A - The matrix
7877a1cb98faSBarry Smith . point - The point in the `DM`
78784a1e0b3eSMatthew G. Knepley . values - The array of values
7879a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
78804a1e0b3eSMatthew G. Knepley 
78814a1e0b3eSMatthew G. Knepley   Level: intermediate
78824a1e0b3eSMatthew G. Knepley 
78831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
78844a1e0b3eSMatthew G. Knepley @*/
7885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7886d71ae5a4SJacob Faibussowitsch {
788771f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
788871f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
788971f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
789071f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
789171f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
789271f0bbf9SMatthew G. Knepley 
789371f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
789471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
78959566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
789671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
78979566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
789871f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
789971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
79009566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
790171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
79029566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
790371f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
790471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
790571f0bbf9SMatthew G. Knepley 
79069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
790871f0bbf9SMatthew G. Knepley 
79099566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7910d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
79114a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
791271f0bbf9SMatthew G. Knepley   if (ierr) {
791371f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
791471f0bbf9SMatthew G. Knepley 
79159566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
79169566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
79179566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
79189566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79199566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
79209566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7921d3d1a6afSToby Isaac   }
792271f0bbf9SMatthew G. Knepley 
79239566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79249566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
79259566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
79263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7927552f7358SJed Brown }
7928552f7358SJed Brown 
7929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7930d71ae5a4SJacob Faibussowitsch {
7931de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
7932de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7933de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7934de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
793517c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7936de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7937412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
79384ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7939de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7940de41b84cSMatthew G. Knepley 
7941de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7942de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7943de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
79449566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7945de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
79469566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7947de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
79489566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7949de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
79509566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7951de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7952de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
79539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
795463a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
79559566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
79569566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7957de41b84cSMatthew G. Knepley   /* Column indices */
79589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79594ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7960de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7961de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
79629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7963de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
7964de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7965de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
7966de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
7967de41b84cSMatthew G. Knepley       ++q;
7968de41b84cSMatthew G. Knepley     }
7969de41b84cSMatthew G. Knepley   }
7970de41b84cSMatthew G. Knepley   numCPoints = q;
7971de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
7972de41b84cSMatthew G. Knepley     PetscInt fdof;
7973de41b84cSMatthew G. Knepley 
79749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
79754ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7976de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
79779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7978de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
7979de41b84cSMatthew G. Knepley     }
7980de41b84cSMatthew G. Knepley     numCIndices += dof;
7981de41b84cSMatthew G. Knepley   }
7982de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
7983de41b84cSMatthew G. Knepley   /* Row indices */
79849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7985412e9a14SMatthew G. Knepley   {
7986012bc364SMatthew G. Knepley     DMPlexTransform tr;
7987012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7988012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7989012bc364SMatthew G. Knepley 
79909566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
79919566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
79929566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7993012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
79949566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7995412e9a14SMatthew G. Knepley   }
79969566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
7997de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7998de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
79999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8000de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
80019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8002de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8003de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
80049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
80054ca5e9f5SMatthew G. Knepley         if (!dof) continue;
80069371c9d4SSatish Balay         for (s = 0; s < q; ++s)
80079371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
80084ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8009de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8010de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8011de41b84cSMatthew G. Knepley         ++q;
8012de41b84cSMatthew G. Knepley       }
8013de41b84cSMatthew G. Knepley     }
80149566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8015de41b84cSMatthew G. Knepley   }
8016de41b84cSMatthew G. Knepley   numFPoints = q;
8017de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8018de41b84cSMatthew G. Knepley     PetscInt fdof;
8019de41b84cSMatthew G. Knepley 
80209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
80214ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8022de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
80239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8024de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8025de41b84cSMatthew G. Knepley     }
8026de41b84cSMatthew G. Knepley     numFIndices += dof;
8027de41b84cSMatthew G. Knepley   }
8028de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8029de41b84cSMatthew G. Knepley 
80301dca8a05SBarry 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);
80311dca8a05SBarry 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);
80329566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80339566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8034de41b84cSMatthew G. Knepley   if (numFields) {
80354acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
80364acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
80374acb8e1eSToby Isaac 
80384acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8041de41b84cSMatthew G. Knepley     }
80424acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
80439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
80449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
80454acb8e1eSToby Isaac     }
80464acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
80479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
80489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
80494acb8e1eSToby Isaac     }
80504acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80519566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80529566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8053de41b84cSMatthew G. Knepley     }
8054de41b84cSMatthew G. Knepley   } else {
80554acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
80564acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
80574acb8e1eSToby Isaac 
80589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
80599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
80604acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
80614acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
80624acb8e1eSToby Isaac 
80639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
80649566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8065de41b84cSMatthew G. Knepley     }
80664acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
80674acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
80684acb8e1eSToby Isaac 
80699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
80709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8071de41b84cSMatthew G. Knepley     }
80729566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
80739566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8074de41b84cSMatthew G. Knepley   }
80759566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
80764acb8e1eSToby Isaac   /* TODO: flips */
8077d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8078de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8079de41b84cSMatthew G. Knepley   if (ierr) {
8080de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8081de41b84cSMatthew G. Knepley 
80829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
80839566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
80849566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
80859566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80869566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8087de41b84cSMatthew G. Knepley   }
80889566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
80899566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
80909566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80919566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
80923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8093de41b84cSMatthew G. Knepley }
8094de41b84cSMatthew G. Knepley 
8095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8096d71ae5a4SJacob Faibussowitsch {
80977c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
80987c927364SMatthew G. Knepley   PetscInt       *cpoints = NULL;
80997c927364SMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
810017c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8101412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
81027c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
81037c927364SMatthew G. Knepley 
81047c927364SMatthew G. Knepley   PetscFunctionBegin;
81057c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
81067c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
81079566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
81087c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
81099566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
81107c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
81119566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
81127c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
81139566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
81147c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
81159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
811663a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
81179566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
81189566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
81197c927364SMatthew G. Knepley   /* Column indices */
81209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81217c927364SMatthew G. Knepley   maxFPoints = numCPoints;
81227c927364SMatthew G. Knepley   /* Compress out points not in the section */
81237c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
81249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
81257c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
81267c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
81277c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
81287c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
81297c927364SMatthew G. Knepley       ++q;
81307c927364SMatthew G. Knepley     }
81317c927364SMatthew G. Knepley   }
81327c927364SMatthew G. Knepley   numCPoints = q;
81337c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
81347c927364SMatthew G. Knepley     PetscInt fdof;
81357c927364SMatthew G. Knepley 
81369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
81377c927364SMatthew G. Knepley     if (!dof) continue;
81387c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
81399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
81407c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
81417c927364SMatthew G. Knepley     }
81427c927364SMatthew G. Knepley     numCIndices += dof;
81437c927364SMatthew G. Knepley   }
81447c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
81457c927364SMatthew G. Knepley   /* Row indices */
81469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8147412e9a14SMatthew G. Knepley   {
8148012bc364SMatthew G. Knepley     DMPlexTransform tr;
8149012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8150012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8151012bc364SMatthew G. Knepley 
81529566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
81539566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
81549566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8155012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
81569566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8157412e9a14SMatthew G. Knepley   }
81589566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
81597c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
81607c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
81619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
81627c927364SMatthew G. Knepley     /* Compress out points not in the section */
81639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
81647c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
81657c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
81669566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
81677c927364SMatthew G. Knepley         if (!dof) continue;
81689371c9d4SSatish Balay         for (s = 0; s < q; ++s)
81699371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
81707c927364SMatthew G. Knepley         if (s < q) continue;
81717c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
81727c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
81737c927364SMatthew G. Knepley         ++q;
81747c927364SMatthew G. Knepley       }
81757c927364SMatthew G. Knepley     }
81769566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
81777c927364SMatthew G. Knepley   }
81787c927364SMatthew G. Knepley   numFPoints = q;
81797c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
81807c927364SMatthew G. Knepley     PetscInt fdof;
81817c927364SMatthew G. Knepley 
81829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
81837c927364SMatthew G. Knepley     if (!dof) continue;
81847c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
81859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
81867c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
81877c927364SMatthew G. Knepley     }
81887c927364SMatthew G. Knepley     numFIndices += dof;
81897c927364SMatthew G. Knepley   }
81907c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
81917c927364SMatthew G. Knepley 
81921dca8a05SBarry 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);
81931dca8a05SBarry 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);
81947c927364SMatthew G. Knepley   if (numFields) {
81954acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
81964acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
81974acb8e1eSToby Isaac 
81984acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
81999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82009566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
82017c927364SMatthew G. Knepley     }
82024acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
82039566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82049566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
82054acb8e1eSToby Isaac     }
82064acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
82079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
82094acb8e1eSToby Isaac     }
82104acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82119566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82129566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
82137c927364SMatthew G. Knepley     }
82147c927364SMatthew G. Knepley   } else {
82154acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
82164acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
82174acb8e1eSToby Isaac 
82189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82204acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
82214acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
82224acb8e1eSToby Isaac 
82239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
82257c927364SMatthew G. Knepley     }
82264acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
82274acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
82284acb8e1eSToby Isaac 
82299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
82317c927364SMatthew G. Knepley     }
82329566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82339566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82347c927364SMatthew G. Knepley   }
82359566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
82369566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
82373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82387c927364SMatthew G. Knepley }
82397c927364SMatthew G. Knepley 
82407cd05799SMatthew G. Knepley /*@C
82417cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
82427cd05799SMatthew G. Knepley 
82437cd05799SMatthew G. Knepley   Input Parameter:
8244a1cb98faSBarry Smith . dm   - The `DMPLEX` object
82457cd05799SMatthew G. Knepley 
82467cd05799SMatthew G. Knepley   Output Parameter:
82477cd05799SMatthew G. Knepley . cellHeight - The height of a cell
82487cd05799SMatthew G. Knepley 
82497cd05799SMatthew G. Knepley   Level: developer
82507cd05799SMatthew G. Knepley 
82511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
82527cd05799SMatthew G. Knepley @*/
8253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8254d71ae5a4SJacob Faibussowitsch {
8255552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8256552f7358SJed Brown 
8257552f7358SJed Brown   PetscFunctionBegin;
8258552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8259dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
8260552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
82613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8262552f7358SJed Brown }
8263552f7358SJed Brown 
82647cd05799SMatthew G. Knepley /*@C
82657cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
82667cd05799SMatthew G. Knepley 
82677cd05799SMatthew G. Knepley   Input Parameters:
8268a1cb98faSBarry Smith + dm   - The `DMPLEX` object
82697cd05799SMatthew G. Knepley - cellHeight - The height of a cell
82707cd05799SMatthew G. Knepley 
82717cd05799SMatthew G. Knepley   Level: developer
82727cd05799SMatthew G. Knepley 
82731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
82747cd05799SMatthew G. Knepley @*/
8275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8276d71ae5a4SJacob Faibussowitsch {
8277552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8278552f7358SJed Brown 
8279552f7358SJed Brown   PetscFunctionBegin;
8280552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8281552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
82823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8283552f7358SJed Brown }
8284552f7358SJed Brown 
8285e6139122SMatthew G. Knepley /*@
8286e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
8287e6139122SMatthew G. Knepley 
8288e6139122SMatthew G. Knepley   Input Parameter:
8289a1cb98faSBarry Smith . dm - The `DMPLEX` object
8290e6139122SMatthew G. Knepley 
8291e6139122SMatthew G. Knepley   Output Parameters:
829220f4b53cSBarry Smith + gcStart - The first ghost cell, or `NULL`
829320f4b53cSBarry Smith - gcEnd   - The upper bound on ghost cells, or `NULL`
8294e6139122SMatthew G. Knepley 
82952a9f31c0SMatthew G. Knepley   Level: advanced
8296e6139122SMatthew G. Knepley 
82971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
8298e6139122SMatthew G. Knepley @*/
8299d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8300d71ae5a4SJacob Faibussowitsch {
8301412e9a14SMatthew G. Knepley   DMLabel ctLabel;
8302e6139122SMatthew G. Knepley 
8303e6139122SMatthew G. Knepley   PetscFunctionBegin;
8304e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
83069566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8307695799ffSMatthew G. Knepley   // Reset label for fast lookup
8308695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
83093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8310e6139122SMatthew G. Knepley }
8311e6139122SMatthew G. Knepley 
8312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8313d71ae5a4SJacob Faibussowitsch {
8314552f7358SJed Brown   PetscSection section, globalSection;
8315552f7358SJed Brown   PetscInt    *numbers, p;
8316552f7358SJed Brown 
8317552f7358SJed Brown   PetscFunctionBegin;
8318d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
83199566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
83209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
832148a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
83229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
83239566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
83249566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8325552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
83269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8327ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8328ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8329552f7358SJed Brown   }
83309566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8331ef48cebcSMatthew G. Knepley   if (globalSize) {
8332ef48cebcSMatthew G. Knepley     PetscLayout layout;
83339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
83349566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
83359566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8336ef48cebcSMatthew G. Knepley   }
83379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
83389566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
83393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8340552f7358SJed Brown }
8341552f7358SJed Brown 
8342d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8343d71ae5a4SJacob Faibussowitsch {
8344412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8345552f7358SJed Brown 
8346552f7358SJed Brown   PetscFunctionBegin;
83479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
83489566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
83499566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
83509566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
83513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8352552f7358SJed Brown }
835381ed3555SMatthew G. Knepley 
83548dab3259SMatthew G. Knepley /*@
83557cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
83567cd05799SMatthew G. Knepley 
83577cd05799SMatthew G. Knepley   Input Parameter:
8358a1cb98faSBarry Smith . dm   - The `DMPLEX` object
83597cd05799SMatthew G. Knepley 
83607cd05799SMatthew G. Knepley   Output Parameter:
83617cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
83627cd05799SMatthew G. Knepley 
83637cd05799SMatthew G. Knepley   Level: developer
83647cd05799SMatthew G. Knepley 
83651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
83667cd05799SMatthew G. Knepley @*/
8367d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8368d71ae5a4SJacob Faibussowitsch {
836981ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
837081ed3555SMatthew G. Knepley 
837181ed3555SMatthew G. Knepley   PetscFunctionBegin;
837281ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83739566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8374552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
83753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8376552f7358SJed Brown }
8377552f7358SJed Brown 
8378d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8379d71ae5a4SJacob Faibussowitsch {
8380412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
838181ed3555SMatthew G. Knepley 
838281ed3555SMatthew G. Knepley   PetscFunctionBegin;
838381ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
83859566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
83863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
838781ed3555SMatthew G. Knepley }
838881ed3555SMatthew G. Knepley 
83898dab3259SMatthew G. Knepley /*@
83906aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
83917cd05799SMatthew G. Knepley 
83927cd05799SMatthew G. Knepley   Input Parameter:
8393a1cb98faSBarry Smith . dm   - The `DMPLEX` object
83947cd05799SMatthew G. Knepley 
83957cd05799SMatthew G. Knepley   Output Parameter:
83967cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
83977cd05799SMatthew G. Knepley 
83987cd05799SMatthew G. Knepley   Level: developer
83997cd05799SMatthew G. Knepley 
84001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
84017cd05799SMatthew G. Knepley @*/
8402d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8403d71ae5a4SJacob Faibussowitsch {
8404552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8405552f7358SJed Brown 
8406552f7358SJed Brown   PetscFunctionBegin;
8407552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84089566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8409552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
84103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8411552f7358SJed Brown }
8412552f7358SJed Brown 
84138dab3259SMatthew G. Knepley /*@
8414966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8415966484cfSJed Brown 
841620f4b53cSBarry Smith   Collective
84177cd05799SMatthew G. Knepley 
84187cd05799SMatthew G. Knepley   Input Parameter:
8419a1cb98faSBarry Smith . dm   - The `DMPLEX` object
84207cd05799SMatthew G. Knepley 
84217cd05799SMatthew G. Knepley   Output Parameter:
84227cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
84237cd05799SMatthew G. Knepley 
8424a1cb98faSBarry Smith   Level: developer
8425966484cfSJed Brown 
8426a1cb98faSBarry Smith   Notes:
8427a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8428966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8429966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8430966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8431966484cfSJed Brown 
8432966484cfSJed Brown   The partitioned mesh is
8433966484cfSJed Brown ```
8434966484cfSJed Brown  (2)--0--(3)--1--(4)    (1)--0--(2)
8435966484cfSJed Brown ```
8436966484cfSJed Brown   and its global numbering is
8437966484cfSJed Brown ```
8438966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8439966484cfSJed Brown ```
8440966484cfSJed Brown   Then the global numbering is provided as
8441966484cfSJed Brown ```
8442966484cfSJed Brown [0] Number of indices in set 5
8443966484cfSJed Brown [0] 0 0
8444966484cfSJed Brown [0] 1 1
8445966484cfSJed Brown [0] 2 3
8446966484cfSJed Brown [0] 3 4
8447966484cfSJed Brown [0] 4 -6
8448966484cfSJed Brown [1] Number of indices in set 3
8449966484cfSJed Brown [1] 0 2
8450966484cfSJed Brown [1] 1 5
8451966484cfSJed Brown [1] 2 6
8452966484cfSJed Brown ```
8453966484cfSJed Brown 
84541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
84557cd05799SMatthew G. Knepley @*/
8456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8457d71ae5a4SJacob Faibussowitsch {
8458ef48cebcSMatthew G. Knepley   IS        nums[4];
8459862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8460ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
84610c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8462ef48cebcSMatthew G. Knepley 
8463ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8464ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
84660c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
84679566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
84680c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8469862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8470862913ffSStefano Zampini     PetscInt end;
8471862913ffSStefano Zampini 
8472862913ffSStefano Zampini     depths[d] = depth - d;
84739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
84740c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8475862913ffSStefano Zampini   }
84760c15888dSMatthew G. Knepley   if (empty)
84770c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
84780c15888dSMatthew G. Knepley       depths[d] = -1;
84790c15888dSMatthew G. Knepley       starts[d] = -1;
84800c15888dSMatthew G. Knepley     }
84810c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
84821c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8483ad540459SPierre 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]);
84840c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8485ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8486ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8487ef48cebcSMatthew G. Knepley 
84889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
84899566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8490ef48cebcSMatthew G. Knepley     shift += gsize;
8491ef48cebcSMatthew G. Knepley   }
8492*d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
84939566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
84943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8495ef48cebcSMatthew G. Knepley }
8496ef48cebcSMatthew G. Knepley 
849708a22f4bSMatthew G. Knepley /*@
849808a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
849908a22f4bSMatthew G. Knepley 
850008a22f4bSMatthew G. Knepley   Input Parameter:
8501a1cb98faSBarry Smith . dm - The `DMPLEX` object
850208a22f4bSMatthew G. Knepley 
850308a22f4bSMatthew G. Knepley   Output Parameter:
850408a22f4bSMatthew G. Knepley . ranks - The rank field
850508a22f4bSMatthew G. Knepley 
8506a1cb98faSBarry Smith   Options Database Key:
850720f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
850808a22f4bSMatthew G. Knepley 
850908a22f4bSMatthew G. Knepley   Level: intermediate
851008a22f4bSMatthew G. Knepley 
85111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
851208a22f4bSMatthew G. Knepley @*/
8513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8514d71ae5a4SJacob Faibussowitsch {
851508a22f4bSMatthew G. Knepley   DM             rdm;
851608a22f4bSMatthew G. Knepley   PetscFE        fe;
851708a22f4bSMatthew G. Knepley   PetscScalar   *r;
851808a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8519a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
852008a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8521a55f9a55SMatthew G. Knepley   PetscBool      simplex;
852208a22f4bSMatthew G. Knepley 
852308a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8524f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8525f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
85269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
85279566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
85289566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
85299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
85309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8531a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
85329566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
85339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
85349566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
85359566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85369566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
85379566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
85389566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
85399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
854008a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
854108a22f4bSMatthew G. Knepley     PetscScalar *lr;
854208a22f4bSMatthew G. Knepley 
85439566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
854471f09efeSPierre Jolivet     if (lr) *lr = rank;
854508a22f4bSMatthew G. Knepley   }
85469566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
85479566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
85483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
854908a22f4bSMatthew G. Knepley }
855008a22f4bSMatthew G. Knepley 
8551ca8062c8SMatthew G. Knepley /*@
855218e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
855318e14f0cSMatthew G. Knepley 
855418e14f0cSMatthew G. Knepley   Input Parameters:
855520f4b53cSBarry Smith + dm    - The `DMPLEX`
855620f4b53cSBarry Smith - label - The `DMLabel`
855718e14f0cSMatthew G. Knepley 
855818e14f0cSMatthew G. Knepley   Output Parameter:
855918e14f0cSMatthew G. Knepley . val - The label value field
856018e14f0cSMatthew G. Knepley 
856120f4b53cSBarry Smith   Options Database Key:
856220f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
856318e14f0cSMatthew G. Knepley 
856418e14f0cSMatthew G. Knepley   Level: intermediate
856518e14f0cSMatthew G. Knepley 
85661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
856718e14f0cSMatthew G. Knepley @*/
8568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8569d71ae5a4SJacob Faibussowitsch {
857018e14f0cSMatthew G. Knepley   DM           rdm;
857118e14f0cSMatthew G. Knepley   PetscFE      fe;
857218e14f0cSMatthew G. Knepley   PetscScalar *v;
857318e14f0cSMatthew G. Knepley   PetscInt     dim, cStart, cEnd, c;
857418e14f0cSMatthew G. Knepley 
857518e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
857618e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
857718e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
857818e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
85799566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
85809566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
85819566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
85829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "label_value"));
85839566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
85849566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85859566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
85869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
85879566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
85889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*val, "label_value"));
85899566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
859018e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
859118e14f0cSMatthew G. Knepley     PetscScalar *lv;
859218e14f0cSMatthew G. Knepley     PetscInt     cval;
859318e14f0cSMatthew G. Knepley 
85949566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
85959566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
859618e14f0cSMatthew G. Knepley     *lv = cval;
859718e14f0cSMatthew G. Knepley   }
85989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
85999566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
86003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
860118e14f0cSMatthew G. Knepley }
860218e14f0cSMatthew G. Knepley 
860318e14f0cSMatthew G. Knepley /*@
8604ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8605ca8062c8SMatthew G. Knepley 
860669916449SMatthew G. Knepley   Input Parameter:
8607a1cb98faSBarry Smith . dm - The `DMPLEX` object
8608a1cb98faSBarry Smith 
8609a1cb98faSBarry Smith   Level: developer
8610ca8062c8SMatthew G. Knepley 
861195eb5ee5SVaclav Hapla   Notes:
861295eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
861395eb5ee5SVaclav Hapla 
861420f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8615ca8062c8SMatthew G. Knepley 
86161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8617ca8062c8SMatthew G. Knepley @*/
8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8619d71ae5a4SJacob Faibussowitsch {
8620ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8621ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8622ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
862357beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
862457beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8625ca8062c8SMatthew G. Knepley 
8626ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8627ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86289566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
86299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
86309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8631ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
86329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8633ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
86349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
86359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8636ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
863742e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
863842e66dfaSMatthew G. Knepley       PetscInt  d;
863942e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
86409371c9d4SSatish Balay         if (cone[c] == cone[d]) {
86419371c9d4SSatish Balay           dup = PETSC_TRUE;
86429371c9d4SSatish Balay           break;
86439371c9d4SSatish Balay         }
864442e66dfaSMatthew G. Knepley       }
86459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
86469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8647ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8648ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8649ca8062c8SMatthew G. Knepley       }
865042e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
865163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
865248a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
86539566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
865463a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
865548a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
86569566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
865763a3b9bcSJacob 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]);
8658f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8659ca8062c8SMatthew G. Knepley       }
866042e66dfaSMatthew G. Knepley     }
86619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
86629371c9d4SSatish Balay     if (p != pp) {
86639371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
86649371c9d4SSatish Balay       continue;
86659371c9d4SSatish Balay     }
86669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
86679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8668ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
86699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
86709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8671ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
86729566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
86739371c9d4SSatish Balay         if (cone[c] != pp) {
86749371c9d4SSatish Balay           c = 0;
86759371c9d4SSatish Balay           break;
86769371c9d4SSatish Balay         }
8677ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8678ca8062c8SMatthew G. Knepley       }
8679ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
868063a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
868148a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
86829566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
868363a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
868448a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
86859566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
868663a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8687ca8062c8SMatthew G. Knepley       }
8688ca8062c8SMatthew G. Knepley     }
8689ca8062c8SMatthew G. Knepley   }
869057beb4faSStefano Zampini   if (storagecheck) {
86919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
86929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
869363a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
869457beb4faSStefano Zampini   }
86953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8696ca8062c8SMatthew G. Knepley }
8697ca8062c8SMatthew G. Knepley 
8698412e9a14SMatthew G. Knepley /*
8699412e9a14SMatthew 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.
8700412e9a14SMatthew G. Knepley */
8701d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8702d71ae5a4SJacob Faibussowitsch {
8703412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8704412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8705412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8706412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8707412e9a14SMatthew G. Knepley 
8708412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8709412e9a14SMatthew G. Knepley   *unsplit = 0;
8710412e9a14SMatthew G. Knepley   switch (ct) {
8711d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
8712d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
8713d71ae5a4SJacob Faibussowitsch     break;
8714412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
87159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8717412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8719412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8720412e9a14SMatthew G. Knepley     }
8721412e9a14SMatthew G. Knepley     break;
8722412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
8723412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
87249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8726412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
87289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8729412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
87309566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8731412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8732412e9a14SMatthew G. Knepley           PetscInt p;
87339371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
87349371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
8735412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
8736412e9a14SMatthew G. Knepley         }
8737412e9a14SMatthew G. Knepley       }
8738412e9a14SMatthew G. Knepley     }
8739412e9a14SMatthew G. Knepley     break;
8740d71ae5a4SJacob Faibussowitsch   default:
8741d71ae5a4SJacob Faibussowitsch     break;
8742412e9a14SMatthew G. Knepley   }
8743412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
87449566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8745412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8746412e9a14SMatthew G. Knepley   }
87473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8748412e9a14SMatthew G. Knepley }
8749412e9a14SMatthew G. Knepley 
8750ca8062c8SMatthew G. Knepley /*@
8751ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8752ca8062c8SMatthew G. Knepley 
8753ca8062c8SMatthew G. Knepley   Input Parameters:
8754a1cb98faSBarry Smith + dm - The `DMPLEX` object
875558723a97SMatthew G. Knepley - cellHeight - Normally 0
8756ca8062c8SMatthew G. Knepley 
8757a1cb98faSBarry Smith   Level: developer
8758a1cb98faSBarry Smith 
875995eb5ee5SVaclav Hapla   Notes:
876095eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
876125c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8762ca8062c8SMatthew G. Knepley 
876320f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
876495eb5ee5SVaclav Hapla 
87651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8766ca8062c8SMatthew G. Knepley @*/
8767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8768d71ae5a4SJacob Faibussowitsch {
8769412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8770412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8771412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8772ca8062c8SMatthew G. Knepley 
8773ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8774ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87759566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
87769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
87779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8778412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8779412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8780412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
878158723a97SMatthew G. Knepley 
87829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
878363a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8784412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8785412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
87869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
878763a3b9bcSJacob 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));
8788412e9a14SMatthew G. Knepley     }
87899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
879058723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
879158723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8792412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
879358723a97SMatthew G. Knepley     }
87949566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8795412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8796412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8797412e9a14SMatthew G. Knepley       PetscInt unsplit;
879842363296SMatthew G. Knepley 
87999566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8800412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
880142363296SMatthew G. Knepley     }
880263a3b9bcSJacob 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));
880342363296SMatthew G. Knepley   }
88043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8805ca8062c8SMatthew G. Knepley }
88069bf0dad6SMatthew G. Knepley 
88079bf0dad6SMatthew G. Knepley /*@
88089bf0dad6SMatthew 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
88099bf0dad6SMatthew G. Knepley 
881020f4b53cSBarry Smith   Collective
8811899ea2b8SJacob Faibussowitsch 
88129bf0dad6SMatthew G. Knepley   Input Parameters:
8813a1cb98faSBarry Smith + dm - The `DMPLEX` object
88149bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
88159bf0dad6SMatthew G. Knepley 
8816a1cb98faSBarry Smith   Level: developer
8817a1cb98faSBarry Smith 
881845da879fSVaclav Hapla   Notes:
881945da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
882045da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
882145da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
882245da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
88239bf0dad6SMatthew G. Knepley 
8824a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
882595eb5ee5SVaclav Hapla 
88261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
88279bf0dad6SMatthew G. Knepley @*/
8828d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
8829d71ae5a4SJacob Faibussowitsch {
8830ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8831899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
88329bf0dad6SMatthew G. Knepley 
88339bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
88349bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88358f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
88363ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
88378f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
88383ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
88393ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8840899ea2b8SJacob Faibussowitsch   }
8841899ea2b8SJacob Faibussowitsch 
88429566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
88439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
88449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8845ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
88469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
88473554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8848412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
8849412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8850ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8851412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8852412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
88539bf0dad6SMatthew G. Knepley 
88549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
88559566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8856412e9a14SMatthew G. Knepley       if (unsplit) continue;
88579566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
88589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
88599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
88609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
88619bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
88629bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
88639bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
88649bf0dad6SMatthew G. Knepley       }
88659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
886663a3b9bcSJacob 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);
88679bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8868d4961f80SStefano Zampini         DMPolytopeType fct;
88699bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
88709bf0dad6SMatthew G. Knepley 
88719566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
88729566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
88739bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
88749bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
88759bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
88769bf0dad6SMatthew G. Knepley         }
887763a3b9bcSJacob 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]);
88789bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8879b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
8880b5a892a1SMatthew G. Knepley             PetscInt v1;
8881b5a892a1SMatthew G. Knepley 
88829566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
888363a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
88849566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
888563a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
88869566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
888763a3b9bcSJacob 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]);
8888b5a892a1SMatthew G. Knepley           }
88899bf0dad6SMatthew G. Knepley         }
88909566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8891412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
88929bf0dad6SMatthew G. Knepley       }
88939566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
88949566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
88959bf0dad6SMatthew G. Knepley     }
88963554e41dSMatthew G. Knepley   }
88973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8898552f7358SJed Brown }
88993913d7c8SMatthew G. Knepley 
8900bb6a34a8SMatthew G. Knepley /*@
8901bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8902bb6a34a8SMatthew G. Knepley 
8903bb6a34a8SMatthew G. Knepley   Input Parameter:
8904a1cb98faSBarry Smith . dm - The `DMPLEX` object
8905a1cb98faSBarry Smith 
8906a1cb98faSBarry Smith   Level: developer
8907bb6a34a8SMatthew G. Knepley 
890895eb5ee5SVaclav Hapla   Notes:
890995eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
891095eb5ee5SVaclav Hapla 
891120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8912bb6a34a8SMatthew G. Knepley 
89131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8914bb6a34a8SMatthew G. Knepley @*/
8915d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
8916d71ae5a4SJacob Faibussowitsch {
8917a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8918bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8919bb6a34a8SMatthew G. Knepley   PetscReal vol;
892051a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8921bb6a34a8SMatthew G. Knepley 
8922bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
89239566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
89249566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
89253ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
89269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8927bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
89289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8929a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
89309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
89313ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
8932412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8933412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8934412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8935412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8936412e9a14SMatthew G. Knepley 
89379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8938412e9a14SMatthew G. Knepley     switch (ct) {
8939412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8940412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8941d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8942d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
8943d71ae5a4SJacob Faibussowitsch       break;
8944d71ae5a4SJacob Faibussowitsch     default:
8945d71ae5a4SJacob Faibussowitsch       break;
8946412e9a14SMatthew G. Knepley     }
8947412e9a14SMatthew G. Knepley     switch (ct) {
8948412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
8949412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8950412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8951d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
8952d71ae5a4SJacob Faibussowitsch       continue;
8953d71ae5a4SJacob Faibussowitsch     default:
8954d71ae5a4SJacob Faibussowitsch       break;
8955412e9a14SMatthew G. Knepley     }
89569566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8957412e9a14SMatthew G. Knepley     if (unsplit) continue;
89589566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
89591dca8a05SBarry 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);
896063a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
89616858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
89626858538eSMatthew G. Knepley     if (depth > 1) {
89639566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
89641dca8a05SBarry 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);
896563a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
8966bb6a34a8SMatthew G. Knepley     }
8967bb6a34a8SMatthew G. Knepley   }
89683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8969bb6a34a8SMatthew G. Knepley }
8970bb6a34a8SMatthew G. Knepley 
897103da9461SVaclav Hapla /*@
897220f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
89737726db96SVaclav Hapla 
897420f4b53cSBarry Smith   Collective
897503da9461SVaclav Hapla 
897603da9461SVaclav Hapla   Input Parameters:
8977a1cb98faSBarry Smith + dm - The `DMPLEX` object
897820f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
8979a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
8980a1cb98faSBarry Smith 
8981a1cb98faSBarry Smith   Level: developer
898203da9461SVaclav Hapla 
8983e83a0d2dSVaclav Hapla   Notes:
8984e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
898503da9461SVaclav Hapla 
8986a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
898795eb5ee5SVaclav Hapla 
8988d7d32a9aSMatthew G. Knepley   Extra roots can come from priodic cuts, where additional points appear on the boundary
8989d7d32a9aSMatthew G. Knepley 
89901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
899103da9461SVaclav Hapla @*/
8992d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
8993d71ae5a4SJacob Faibussowitsch {
89947726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
89957726db96SVaclav Hapla   const PetscInt    *locals;
89967726db96SVaclav Hapla   const PetscSFNode *remotes;
8997f0cfc026SVaclav Hapla   PetscBool          distributed;
89987726db96SVaclav Hapla   MPI_Comm           comm;
89997726db96SVaclav Hapla   PetscMPIInt        rank;
900003da9461SVaclav Hapla 
900103da9461SVaclav Hapla   PetscFunctionBegin;
900203da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90037726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
90047726db96SVaclav Hapla   else pointSF = dm->sf;
90057726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
90067726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
90077726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
90087726db96SVaclav Hapla   {
90097726db96SVaclav Hapla     PetscMPIInt mpiFlag;
90107726db96SVaclav Hapla 
90117726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
90127726db96SVaclav 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);
90137726db96SVaclav Hapla   }
90147726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
90159566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
90167726db96SVaclav Hapla   if (!distributed) {
90177726db96SVaclav 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);
90183ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
90198918e3e2SVaclav Hapla   }
90207726db96SVaclav 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);
90217726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
902203da9461SVaclav Hapla 
90237726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
90247726db96SVaclav Hapla   {
90257726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
90267726db96SVaclav Hapla 
90277726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
90287726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9029d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
90307726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
90317726db96SVaclav Hapla   }
90327726db96SVaclav Hapla 
90337726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
90347726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
90357726db96SVaclav 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);
90367726db96SVaclav Hapla   }
90377726db96SVaclav Hapla 
90387726db96SVaclav Hapla   /* Check there are no cells in interface */
90397726db96SVaclav Hapla   if (!overlap) {
90407726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
90417726db96SVaclav Hapla 
90429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9044f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
90457726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9046f5869d18SMatthew G. Knepley 
90477726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
90487726db96SVaclav Hapla     }
904903da9461SVaclav Hapla   }
9050ece87651SVaclav Hapla 
90517726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
90527726db96SVaclav Hapla   {
90537726db96SVaclav Hapla     const PetscInt *rootdegree;
90547726db96SVaclav Hapla 
90557726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
90567726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9057f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
90587726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9059f5869d18SMatthew G. Knepley       const PetscInt *cone;
9060f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9061f5869d18SMatthew G. Knepley 
90629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
90639566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9064f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9065f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
90667726db96SVaclav Hapla           if (locals) {
90679566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
90687726db96SVaclav Hapla           } else {
90697726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
90707726db96SVaclav Hapla           }
907163a3b9bcSJacob 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]);
9072f5869d18SMatthew G. Knepley         }
9073f5869d18SMatthew G. Knepley       }
9074ece87651SVaclav Hapla     }
90757726db96SVaclav Hapla   }
90763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
907703da9461SVaclav Hapla }
907803da9461SVaclav Hapla 
90797f9d8d6cSVaclav Hapla /*@
908020f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
90817f9d8d6cSVaclav Hapla 
90827f9d8d6cSVaclav Hapla   Input Parameter:
9083a1cb98faSBarry Smith . dm - The `DMPLEX` object
9084a1cb98faSBarry Smith 
9085a1cb98faSBarry Smith   Level: developer
90867f9d8d6cSVaclav Hapla 
90877f9d8d6cSVaclav Hapla   Notes:
90887f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
90897f9d8d6cSVaclav Hapla 
909020f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
90917f9d8d6cSVaclav Hapla 
909220f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
90937f9d8d6cSVaclav Hapla 
90941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
90957f9d8d6cSVaclav Hapla @*/
9096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9097d71ae5a4SJacob Faibussowitsch {
90987f9d8d6cSVaclav Hapla   PetscInt cellHeight;
90997f9d8d6cSVaclav Hapla 
9100b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91017f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
91029566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
91039566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
91049566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
91059566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9106d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
91079566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
91083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9109b5a892a1SMatthew G. Knepley }
9110b5a892a1SMatthew G. Knepley 
91119371c9d4SSatish Balay typedef struct cell_stats {
9112068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9113068a5610SStefano Zampini   PetscInt  count;
9114068a5610SStefano Zampini } cell_stats_t;
9115068a5610SStefano Zampini 
9116d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9117d71ae5a4SJacob Faibussowitsch {
9118068a5610SStefano Zampini   PetscInt i, N = *len;
9119068a5610SStefano Zampini 
9120068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9121068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9122068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9123068a5610SStefano Zampini 
9124068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9125068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9126068a5610SStefano Zampini     B->sum += A->sum;
9127068a5610SStefano Zampini     B->squaresum += A->squaresum;
9128068a5610SStefano Zampini     B->count += A->count;
9129068a5610SStefano Zampini   }
9130068a5610SStefano Zampini }
9131068a5610SStefano Zampini 
9132068a5610SStefano Zampini /*@
913343fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9134068a5610SStefano Zampini 
913520f4b53cSBarry Smith   Collective
91368261a58bSMatthew G. Knepley 
9137068a5610SStefano Zampini   Input Parameters:
9138a1cb98faSBarry Smith + dm        - The `DMPLEX` object
913920f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9140a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9141a1cb98faSBarry Smith 
9142a1cb98faSBarry Smith   Level: developer
9143068a5610SStefano Zampini 
914495eb5ee5SVaclav Hapla   Notes:
914595eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
914695eb5ee5SVaclav Hapla 
9147a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9148068a5610SStefano Zampini 
91491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9150068a5610SStefano Zampini @*/
9151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9152d71ae5a4SJacob Faibussowitsch {
9153068a5610SStefano Zampini   DM           dmCoarse;
915443fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
915543fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
915643fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
915743fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9158412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
915943fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9160068a5610SStefano Zampini 
9161068a5610SStefano Zampini   PetscFunctionBegin;
9162068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9163068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9164068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9165068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9166068a5610SStefano Zampini   stats.count                 = 0;
9167068a5610SStefano Zampini 
91689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
91699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
91709566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
91719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
91729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
91739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9174412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9175068a5610SStefano Zampini     PetscInt  i;
9176068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9177068a5610SStefano Zampini 
91789566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
917963a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
918043fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9181068a5610SStefano Zampini       frobJ += J[i] * J[i];
9182068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9183068a5610SStefano Zampini     }
9184068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9185068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9186068a5610SStefano Zampini 
9187068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9188068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9189068a5610SStefano Zampini     stats.sum += cond;
9190068a5610SStefano Zampini     stats.squaresum += cond2;
9191068a5610SStefano Zampini     stats.count++;
91928261a58bSMatthew G. Knepley     if (output && cond > limit) {
919343fa8764SMatthew G. Knepley       PetscSection coordSection;
919443fa8764SMatthew G. Knepley       Vec          coordsLocal;
919543fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
919643fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
919743fa8764SMatthew G. Knepley 
91989566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
91999566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
92009566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
920163a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
920243fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
920363a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
920443fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
92059566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
92069566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
920743fa8764SMatthew G. Knepley         }
92089566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
920943fa8764SMatthew G. Knepley       }
92109566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
921143fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
921243fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
921343fa8764SMatthew G. Knepley 
921443fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
921543fa8764SMatthew G. Knepley           PetscReal len;
921643fa8764SMatthew G. Knepley 
92179566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
921863a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
921943fa8764SMatthew G. Knepley         }
922043fa8764SMatthew G. Knepley       }
92219566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
92229566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
922343fa8764SMatthew G. Knepley     }
9224068a5610SStefano Zampini   }
92259566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9226068a5610SStefano Zampini 
9227068a5610SStefano Zampini   if (size > 1) {
9228068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9229068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9230068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9231068a5610SStefano Zampini     MPI_Op       statReduce;
9232068a5610SStefano Zampini 
92339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
92349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
92359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
92369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
92379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
92389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9239068a5610SStefano Zampini   } else {
92409566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9241068a5610SStefano Zampini   }
9242dd400576SPatrick Sanan   if (rank == 0) {
9243068a5610SStefano Zampini     count = globalStats.count;
9244068a5610SStefano Zampini     min   = globalStats.min;
9245068a5610SStefano Zampini     max   = globalStats.max;
9246068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9247068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9248068a5610SStefano Zampini   }
9249068a5610SStefano Zampini 
925048a46eb9SPierre 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));
92519566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9252068a5610SStefano Zampini 
92539566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9254068a5610SStefano Zampini   if (dmCoarse) {
9255068a5610SStefano Zampini     PetscBool isplex;
9256068a5610SStefano Zampini 
92579566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
92581baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9259068a5610SStefano Zampini   }
92603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9261068a5610SStefano Zampini }
9262068a5610SStefano Zampini 
9263f108dbd7SJacob Faibussowitsch /*@
9264f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9265f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9266f108dbd7SJacob Faibussowitsch 
926720f4b53cSBarry Smith   Collective
9268f108dbd7SJacob Faibussowitsch 
9269f108dbd7SJacob Faibussowitsch   Input Parameters:
9270a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9271a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9272f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9273f108dbd7SJacob Faibussowitsch 
9274f108dbd7SJacob Faibussowitsch   Output Parameters:
927520f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9276a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9277f108dbd7SJacob Faibussowitsch 
9278f108dbd7SJacob Faibussowitsch   Options Database Keys:
9279a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9280f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
9281f108dbd7SJacob Faibussowitsch 
9282a1cb98faSBarry Smith   Level: intermediate
9283a1cb98faSBarry Smith 
9284f108dbd7SJacob Faibussowitsch   Notes:
9285f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
9286f108dbd7SJacob Faibussowitsch 
9287a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9288f108dbd7SJacob Faibussowitsch 
9289f108dbd7SJacob 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
9290f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9291f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9292f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9293f108dbd7SJacob Faibussowitsch 
9294f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9295f108dbd7SJacob Faibussowitsch 
9296a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9297f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9298f108dbd7SJacob Faibussowitsch 
9299f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9300f108dbd7SJacob Faibussowitsch 
93011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9302f108dbd7SJacob Faibussowitsch @*/
9303d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9304d71ae5a4SJacob Faibussowitsch {
93056ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
93066ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
93076ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9308f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
93096ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9310f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9311f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9312f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9313f108dbd7SJacob Faibussowitsch   IS                     glob;
9314f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9315f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9316f108dbd7SJacob Faibussowitsch 
9317f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9318f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9319ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
9320f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
93216bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
93229566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
93239566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
932463a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
93256ed19f2fSJacob Faibussowitsch   {
93266ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
93276ed19f2fSJacob Faibussowitsch 
93289566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9329f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9330f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9331f108dbd7SJacob Faibussowitsch 
93329566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
933398921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9334f108dbd7SJacob Faibussowitsch     }
93356ed19f2fSJacob Faibussowitsch   }
9336f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
9337f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
93389566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
93399566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
93409371c9d4SSatish Balay   } else {
93419371c9d4SSatish Balay     *OrthQualLabel = NULL;
93429371c9d4SSatish Balay   }
93439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
93449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
93459566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
93469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
93479566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
93489566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
93499566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
93509566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
93519566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
93529566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
93539566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
93549566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
93559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
93569566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
93579566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
93589566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
93599566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
93609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
93616ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
93626ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9363f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9364f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9365898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9366f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9367f108dbd7SJacob Faibussowitsch 
93686ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9369f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9370f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
93719566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
93729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9373f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
93749566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
93756ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
93766ed19f2fSJacob Faibussowitsch       PetscInt         i;
93776ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9378f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9379f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9380f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9381f108dbd7SJacob Faibussowitsch 
9382f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9383f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
93849566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9385f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
93866ed19f2fSJacob Faibussowitsch       {
93876ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
93886ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
93896ed19f2fSJacob Faibussowitsch 
93909566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
93919566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
93929566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
93936ed19f2fSJacob Faibussowitsch       }
9394f108dbd7SJacob Faibussowitsch 
9395f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9396f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9397f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9398f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9399f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9400addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9401addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9402addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9403f108dbd7SJacob Faibussowitsch       }
9404addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9405addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9406addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9407f108dbd7SJacob Faibussowitsch 
9408f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9409f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9410f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9411f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9412f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9413f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9414f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9415f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9416f108dbd7SJacob Faibussowitsch       }
9417ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9418ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9419f108dbd7SJacob Faibussowitsch     }
94209566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
94219566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9422f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
94236ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9424f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
94259566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9426f108dbd7SJacob Faibussowitsch     }
9427f108dbd7SJacob Faibussowitsch   }
94289566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
94299566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
94309566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
94319566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
94329566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
94339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9434f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
94359566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9436f108dbd7SJacob Faibussowitsch   }
94379566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
94389566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
94399566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
94403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9441f108dbd7SJacob Faibussowitsch }
9442f108dbd7SJacob Faibussowitsch 
9443d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
94441eb70e55SToby Isaac  * interpolator construction */
9445d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9446d71ae5a4SJacob Faibussowitsch {
94471eb70e55SToby Isaac   PetscSection section, newSection, gsection;
94481eb70e55SToby Isaac   PetscSF      sf;
94491eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
94501eb70e55SToby Isaac 
94511eb70e55SToby Isaac   PetscFunctionBegin;
94521eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94531eb70e55SToby Isaac   PetscValidPointer(odm, 2);
94549566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
94559566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9456712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
94571eb70e55SToby Isaac   if (!ghasConstraints) {
94589566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
94591eb70e55SToby Isaac     *odm = dm;
94603ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
94611eb70e55SToby Isaac   }
94629566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
94639566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
94649566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
94659566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
94669566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
94679566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
94689566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
94693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
94701eb70e55SToby Isaac }
94711eb70e55SToby Isaac 
9472d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9473d71ae5a4SJacob Faibussowitsch {
94741eb70e55SToby Isaac   DM        dmco, dmfo;
94751eb70e55SToby Isaac   Mat       interpo;
94761eb70e55SToby Isaac   Vec       rscale;
94771eb70e55SToby Isaac   Vec       cglobalo, clocal;
94781eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
94791eb70e55SToby Isaac   PetscBool regular;
94801eb70e55SToby Isaac 
94811eb70e55SToby Isaac   PetscFunctionBegin;
94829566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
94839566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
94849566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
94859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
94869566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
94879566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
94889566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
94899566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
94909566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
94919566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
94929566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
94939566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
94949566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
94959566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
94969566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
94979566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
94989566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
94999566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
95009566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
95019566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
95029566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
95039566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
95049566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
95059566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
95061eb70e55SToby Isaac   *shift = fglobal;
95079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
95089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
95099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
95109566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
95119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
95129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
95139566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
95149566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
95153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95161eb70e55SToby Isaac }
95171eb70e55SToby Isaac 
9518d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9519d71ae5a4SJacob Faibussowitsch {
95201eb70e55SToby Isaac   PetscObject shifto;
95211eb70e55SToby Isaac   Vec         shift;
95221eb70e55SToby Isaac 
95231eb70e55SToby Isaac   PetscFunctionBegin;
95241eb70e55SToby Isaac   if (!interp) {
95251eb70e55SToby Isaac     Vec rscale;
95261eb70e55SToby Isaac 
95279566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
95289566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
95291eb70e55SToby Isaac   } else {
95309566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
95311eb70e55SToby Isaac   }
95329566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
95331eb70e55SToby Isaac   if (!shifto) {
95349566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
95359566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
95361eb70e55SToby Isaac     shifto = (PetscObject)shift;
95379566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
95381eb70e55SToby Isaac   }
95391eb70e55SToby Isaac   shift = (Vec)shifto;
95409566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
95419566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
95429566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
95433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95441eb70e55SToby Isaac }
95451eb70e55SToby Isaac 
9546bceba477SMatthew G. Knepley /* Pointwise interpolation
9547bceba477SMatthew G. Knepley      Just code FEM for now
9548bceba477SMatthew G. Knepley      u^f = I u^c
95494ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
95504ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
95514ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9552bceba477SMatthew G. Knepley */
9553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9554d71ae5a4SJacob Faibussowitsch {
9555bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9556bceba477SMatthew G. Knepley   PetscInt     m, n;
9557a063dac3SMatthew G. Knepley   void        *ctx;
955868132eb9SMatthew G. Knepley   DM           cdm;
9559cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9560bceba477SMatthew G. Knepley 
9561bceba477SMatthew G. Knepley   PetscFunctionBegin;
95629566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
95639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
95649566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
95659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
956668132eb9SMatthew G. Knepley 
95679566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
95689566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
95699566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
95709566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
95719566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
957268132eb9SMatthew G. Knepley 
95739566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
95749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
95759566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
95769566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
95779566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
95784db47ee9SStefano Zampini   if (scaling) {
95795d1c2e58SMatthew G. Knepley     /* Use naive scaling */
95809566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
95814db47ee9SStefano Zampini   }
95823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9583a063dac3SMatthew G. Knepley }
9584bceba477SMatthew G. Knepley 
9585d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9586d71ae5a4SJacob Faibussowitsch {
95876dbf9973SLawrence Mitchell   VecScatter ctx;
958890748bafSMatthew G. Knepley 
9589a063dac3SMatthew G. Knepley   PetscFunctionBegin;
95909566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
95919566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
95929566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
95933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9594bceba477SMatthew G. Knepley }
9595bceba477SMatthew G. Knepley 
9596d71ae5a4SJacob 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[])
9597d71ae5a4SJacob Faibussowitsch {
959800635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
959900635df3SMatthew G. Knepley   PetscInt       c;
960000635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
96013e9753d6SMatthew G. Knepley }
96023e9753d6SMatthew G. Knepley 
9603d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9604d71ae5a4SJacob Faibussowitsch {
9605b4937a87SMatthew G. Knepley   DM           dmc;
9606b4937a87SMatthew G. Knepley   PetscDS      ds;
9607b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9608b4937a87SMatthew G. Knepley   IS           cellIS;
9609b4937a87SMatthew G. Knepley   PetscFormKey key;
9610b4937a87SMatthew G. Knepley   PetscInt     depth;
9611b4937a87SMatthew G. Knepley 
9612b4937a87SMatthew G. Knepley   PetscFunctionBegin;
96139566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
96149566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
96159566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
96169566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
96179566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
96189566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
96199566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
96209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
96219566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
96229566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
96239566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9624b4937a87SMatthew G. Knepley   key.label = NULL;
9625b4937a87SMatthew G. Knepley   key.value = 0;
9626b4937a87SMatthew G. Knepley   key.field = 0;
9627b4937a87SMatthew G. Knepley   key.part  = 0;
96289566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
96299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
96309566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
96319566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
96329566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
96339566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
96349566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
96359566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
96363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9637b4937a87SMatthew G. Knepley }
9638b4937a87SMatthew G. Knepley 
9639d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9640d71ae5a4SJacob Faibussowitsch {
9641bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9642bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9643bd041c0cSMatthew G. Knepley   void        *ctx;
9644bd041c0cSMatthew G. Knepley   DM           cdm;
9645bd041c0cSMatthew G. Knepley   PetscBool    regular;
9646bd041c0cSMatthew G. Knepley 
9647bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
96483e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
96493e9753d6SMatthew G. Knepley     DM            dmc;
96503e9753d6SMatthew G. Knepley     PetscDS       ds;
9651b4937a87SMatthew G. Knepley     PetscWeakForm wf;
96523e9753d6SMatthew G. Knepley     Vec           u;
96533e9753d6SMatthew G. Knepley     IS            cellIS;
965406ad1575SMatthew G. Knepley     PetscFormKey  key;
96553e9753d6SMatthew G. Knepley     PetscInt      depth;
96563e9753d6SMatthew G. Knepley 
96579566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
96589566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
96599566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
96609566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
96619566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
96629566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
96639566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
96648d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
96659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
96669566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
96679566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
96686528b96dSMatthew G. Knepley     key.label = NULL;
96696528b96dSMatthew G. Knepley     key.value = 0;
96706528b96dSMatthew G. Knepley     key.field = 0;
967106ad1575SMatthew G. Knepley     key.part  = 0;
96729566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
96739566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
96748d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
96759566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
96763e9753d6SMatthew G. Knepley   } else {
96779566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
96789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
96799566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
96809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9681bd041c0cSMatthew G. Knepley 
96829566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
96839566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
96849566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
96859566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9686bd041c0cSMatthew G. Knepley 
96879566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
96889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
96899566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
96909566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
96913e9753d6SMatthew G. Knepley   }
96929566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
96933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9694bd041c0cSMatthew G. Knepley }
9695bd041c0cSMatthew G. Knepley 
96960aef6b92SMatthew G. Knepley /*@
96970aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
96980aef6b92SMatthew G. Knepley 
96990aef6b92SMatthew G. Knepley   Input Parameter:
9700a1cb98faSBarry Smith . dm - The `DMPLEX` object
97010aef6b92SMatthew G. Knepley 
97020aef6b92SMatthew G. Knepley   Output Parameter:
97030aef6b92SMatthew G. Knepley . regular - The flag
97040aef6b92SMatthew G. Knepley 
97050aef6b92SMatthew G. Knepley   Level: intermediate
97060aef6b92SMatthew G. Knepley 
97071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
97080aef6b92SMatthew G. Knepley @*/
9709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
9710d71ae5a4SJacob Faibussowitsch {
97110aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97120aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9713dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
97140aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
97153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97160aef6b92SMatthew G. Knepley }
97170aef6b92SMatthew G. Knepley 
97180aef6b92SMatthew G. Knepley /*@
97190aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
97200aef6b92SMatthew G. Knepley 
97210aef6b92SMatthew G. Knepley   Input Parameters:
9722a1cb98faSBarry Smith + dm - The `DMPLEX` object
97230aef6b92SMatthew G. Knepley - regular - The flag
97240aef6b92SMatthew G. Knepley 
97250aef6b92SMatthew G. Knepley   Level: intermediate
97260aef6b92SMatthew G. Knepley 
97271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
97280aef6b92SMatthew G. Knepley @*/
9729d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
9730d71ae5a4SJacob Faibussowitsch {
97310aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97320aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97330aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
97343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97350aef6b92SMatthew G. Knepley }
97360aef6b92SMatthew G. Knepley 
9737a68b90caSToby Isaac /*@
9738f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9739a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
9740a68b90caSToby Isaac 
9741a1cb98faSBarry Smith   Not Collective
9742a68b90caSToby Isaac 
9743f899ff85SJose E. Roman   Input Parameter:
9744a1cb98faSBarry Smith . dm - The `DMPLEX` object
9745a68b90caSToby Isaac 
9746a68b90caSToby Isaac   Output Parameters:
974720f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
974820f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection`
9749a68b90caSToby Isaac 
9750a68b90caSToby Isaac   Level: intermediate
9751a68b90caSToby Isaac 
97521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
9753a68b90caSToby Isaac @*/
9754d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9755d71ae5a4SJacob Faibussowitsch {
9756a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9757a68b90caSToby Isaac 
9758a68b90caSToby Isaac   PetscFunctionBegin;
9759a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97609566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9761a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9762a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
97633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9764a68b90caSToby Isaac }
9765a68b90caSToby Isaac 
9766a68b90caSToby Isaac /*@
9767f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9768f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9769a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9770a68b90caSToby Isaac 
977120f4b53cSBarry Smith   Collective
9772a68b90caSToby Isaac 
9773a68b90caSToby Isaac   Input Parameters:
9774a1cb98faSBarry Smith + dm - The `DMPLEX` object
9775a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
9776a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9777a1cb98faSBarry Smith - anchorIS - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9778a68b90caSToby Isaac 
9779a68b90caSToby Isaac   Level: intermediate
9780a68b90caSToby Isaac 
9781a1cb98faSBarry Smith   Notes:
9782a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
9783a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
9784a1cb98faSBarry Smith 
978520f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
9786a1cb98faSBarry Smith 
97871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9788a68b90caSToby Isaac @*/
9789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9790d71ae5a4SJacob Faibussowitsch {
9791a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
9792e228b242SToby Isaac   PetscMPIInt result;
9793a68b90caSToby Isaac 
9794a68b90caSToby Isaac   PetscFunctionBegin;
9795a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9796e228b242SToby Isaac   if (anchorSection) {
9797e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
97989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
97991dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
9800e228b242SToby Isaac   }
9801e228b242SToby Isaac   if (anchorIS) {
9802e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
98039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
98041dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
9805e228b242SToby Isaac   }
9806a68b90caSToby Isaac 
98079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
98089566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9809a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9810a68b90caSToby Isaac 
98119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
98129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9813a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9814a68b90caSToby Isaac 
9815cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9816a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
9817a68b90caSToby Isaac     const PetscInt *anchors;
9818a68b90caSToby Isaac 
98199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
98209566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
98219566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
9822a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9823a68b90caSToby Isaac       PetscInt p;
9824a68b90caSToby Isaac 
9825a68b90caSToby Isaac       p = anchors[a];
9826a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9827a68b90caSToby Isaac         PetscInt dof;
9828a68b90caSToby Isaac 
98299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9830a68b90caSToby Isaac         if (dof) {
98319566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
983263a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
9833a68b90caSToby Isaac         }
9834a68b90caSToby Isaac       }
9835a68b90caSToby Isaac     }
98369566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
9837a68b90caSToby Isaac   }
9838f7c74593SToby Isaac   /* reset the generic constraints */
98399566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
98403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9841a68b90caSToby Isaac }
9842a68b90caSToby Isaac 
9843d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9844d71ae5a4SJacob Faibussowitsch {
9845f7c74593SToby Isaac   PetscSection anchorSection;
98466995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9847a68b90caSToby Isaac 
9848a68b90caSToby Isaac   PetscFunctionBegin;
9849a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
98519566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
98529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
98536995de1eSToby Isaac   if (numFields) {
9854719ab38cSToby Isaac     PetscInt f;
98559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
9856719ab38cSToby Isaac 
9857719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9858719ab38cSToby Isaac       PetscInt numComp;
9859719ab38cSToby Isaac 
98609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
98619566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
9862719ab38cSToby Isaac     }
98636995de1eSToby Isaac   }
98649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
98659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
98666995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
98676995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
98686995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
98699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
9870a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
98719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9872a68b90caSToby Isaac     if (dof) {
98739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
98749566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
9875a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
98769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
98779566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
9878a68b90caSToby Isaac       }
9879a68b90caSToby Isaac     }
9880a68b90caSToby Isaac   }
98819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
98829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
98833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9884a68b90caSToby Isaac }
9885a68b90caSToby Isaac 
9886d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9887d71ae5a4SJacob Faibussowitsch {
9888f7c74593SToby Isaac   PetscSection    aSec;
9889ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
98900ac89760SToby Isaac   const PetscInt *anchors;
98910ac89760SToby Isaac   PetscInt        numFields, f;
989266ad2231SToby Isaac   IS              aIS;
9893e19f7ee6SMark Adams   MatType         mtype;
9894e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
98950ac89760SToby Isaac 
98960ac89760SToby Isaac   PetscFunctionBegin;
98970ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
98999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
99009566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
99019566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
99029566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
99039566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
99049566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
99059566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
9906e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9907e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9908e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
99099566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
99109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
99119566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
99126995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
99139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
99149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
99159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
99160ac89760SToby Isaac   i[0] = 0;
99179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
99180ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9919f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9920f19733c5SToby Isaac 
99219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
9922f19733c5SToby Isaac     if (!rDof) continue;
99239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99240ac89760SToby Isaac     if (numFields) {
99250ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99260ac89760SToby Isaac         annz = 0;
9927f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9928f19733c5SToby Isaac           a = anchors[rOff + r];
9929ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
99309566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
99310ac89760SToby Isaac           annz += aDof;
99320ac89760SToby Isaac         }
99339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
9935ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99360ac89760SToby Isaac       }
99372f7452b8SBarry Smith     } else {
99380ac89760SToby Isaac       annz = 0;
99399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99400ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9941ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9942ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
99439566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
99440ac89760SToby Isaac         annz += aDof;
99450ac89760SToby Isaac       }
99469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
9948ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99490ac89760SToby Isaac     }
99500ac89760SToby Isaac   }
99510ac89760SToby Isaac   nnz = i[m];
99529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
99530ac89760SToby Isaac   offset = 0;
99540ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
99550ac89760SToby Isaac     if (numFields) {
99560ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99580ac89760SToby Isaac         for (q = 0; q < dof; q++) {
99590ac89760SToby Isaac           PetscInt rDof, rOff, r;
99609566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
99619566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99620ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
99630ac89760SToby Isaac             PetscInt s;
99640ac89760SToby Isaac 
99650ac89760SToby Isaac             a = anchors[rOff + r];
9966ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
99679566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
99689566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
9969ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
99700ac89760SToby Isaac           }
99710ac89760SToby Isaac         }
99720ac89760SToby Isaac       }
99732f7452b8SBarry Smith     } else {
99749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99750ac89760SToby Isaac       for (q = 0; q < dof; q++) {
99760ac89760SToby Isaac         PetscInt rDof, rOff, r;
99779566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
99789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99790ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
99800ac89760SToby Isaac           PetscInt s;
99810ac89760SToby Isaac 
99820ac89760SToby Isaac           a = anchors[rOff + r];
9983ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
99849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
99859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
9986ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
99870ac89760SToby Isaac         }
99880ac89760SToby Isaac       }
99890ac89760SToby Isaac     }
99900ac89760SToby Isaac   }
99919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
99929566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
99939566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
99949566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
99953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99960ac89760SToby Isaac }
99970ac89760SToby Isaac 
9998d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
9999d71ae5a4SJacob Faibussowitsch {
10000f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10001f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1000266ad2231SToby Isaac   Mat          cMat;
1000366ad2231SToby Isaac 
1000466ad2231SToby Isaac   PetscFunctionBegin;
1000566ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1000766ad2231SToby Isaac   if (anchorSection) {
1000844a7f3ddSMatthew G. Knepley     PetscInt Nf;
10009e228b242SToby Isaac 
100109566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
100119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
100129566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
100139566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
100149566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
100159566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
100169566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
100179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1001866ad2231SToby Isaac   }
100193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1002066ad2231SToby Isaac }
10021a93c429eSMatthew G. Knepley 
10022d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10023d71ae5a4SJacob Faibussowitsch {
10024a93c429eSMatthew G. Knepley   IS           subis;
10025a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10026a93c429eSMatthew G. Knepley 
10027a93c429eSMatthew G. Knepley   PetscFunctionBegin;
100289566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1002928b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1003028b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10031a93c429eSMatthew G. Knepley   /* Create subdomain */
100329566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10033a93c429eSMatthew G. Knepley   /* Create submodel */
100349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
100359566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
100369566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
100379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
100389566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10039a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10040a93c429eSMatthew G. Knepley   if (is) {
10041a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10042a93c429eSMatthew G. Knepley     IS              spIS;
10043a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10044a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10045a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10046a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10047a93c429eSMatthew G. Knepley 
100489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
100499566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
100509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
100519566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
100529566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
100539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10054a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10055a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10056a93c429eSMatthew G. Knepley 
100579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10058a93c429eSMatthew G. Knepley       if (gdof > 0) {
10059a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10060a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10061a93c429eSMatthew G. Knepley 
100629566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
100639566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10064a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10065a93c429eSMatthew G. Knepley         }
10066a93c429eSMatthew G. Knepley         subSize += pSubSize;
10067a93c429eSMatthew G. Knepley         if (pSubSize) {
10068a93c429eSMatthew G. Knepley           if (bs < 0) {
10069a93c429eSMatthew G. Knepley             bs = pSubSize;
10070a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10071a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10072a93c429eSMatthew G. Knepley             bs = 1;
10073a93c429eSMatthew G. Knepley           }
10074a93c429eSMatthew G. Knepley         }
10075a93c429eSMatthew G. Knepley       }
10076a93c429eSMatthew G. Knepley     }
10077a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
100789371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
100799371c9d4SSatish Balay     bsLocal[1] = bs;
100809566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
100819371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
100829371c9d4SSatish Balay       bs = 1;
100839371c9d4SSatish Balay     } else {
100849371c9d4SSatish Balay       bs = bsMinMax[0];
100859371c9d4SSatish Balay     }
100869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10087a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10088a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10089a93c429eSMatthew G. Knepley 
100909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10091a93c429eSMatthew G. Knepley       if (gdof > 0) {
10092a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10093a93c429eSMatthew G. Knepley 
100949566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10095a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10096a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10097a93c429eSMatthew G. Knepley 
10098a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10099a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
101009566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
101019566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10102a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10103a93c429eSMatthew G. Knepley           }
101049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
101059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10106ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10107a93c429eSMatthew G. Knepley         }
10108a93c429eSMatthew G. Knepley       }
10109a93c429eSMatthew G. Knepley     }
101109566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
101119566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10112a93c429eSMatthew G. Knepley     if (bs > 1) {
10113a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10114a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10115a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10116a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
101179371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
101189371c9d4SSatish Balay             set = 0;
101199371c9d4SSatish Balay             break;
101209371c9d4SSatish Balay           }
10121a93c429eSMatthew G. Knepley         }
10122a93c429eSMatthew G. Knepley       }
101239566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10124a93c429eSMatthew G. Knepley     }
10125a93c429eSMatthew G. Knepley     /* Attach nullspace */
10126a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10127a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10128a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10129a93c429eSMatthew G. Knepley     }
10130a93c429eSMatthew G. Knepley     if (f < Nf) {
10131a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
101329566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
101336823f3c5SBlaise Bourdin 
101349566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
101359566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10136a93c429eSMatthew G. Knepley     }
10137a93c429eSMatthew G. Knepley   }
101383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10139a93c429eSMatthew G. Knepley }
10140c0f0dcc3SMatthew G. Knepley 
10141c0f0dcc3SMatthew G. Knepley /*@
10142c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10143c0f0dcc3SMatthew G. Knepley 
10144a1cb98faSBarry Smith   Input Parameters:
10145a1cb98faSBarry Smith + dm - The `DM`
10146a1cb98faSBarry Smith - dummy - unused argument
10147a1cb98faSBarry Smith 
10148a1cb98faSBarry Smith   Options Database Key:
10149a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10150c0f0dcc3SMatthew G. Knepley 
10151c0f0dcc3SMatthew G. Knepley   Level: developer
10152c0f0dcc3SMatthew G. Knepley 
101531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10154c0f0dcc3SMatthew G. Knepley @*/
10155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10156d71ae5a4SJacob Faibussowitsch {
10157e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
10158c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
10159c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
10160c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
10161c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
10162c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
10163c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
10164c0f0dcc3SMatthew G. Knepley   const char        *name;
10165e5ed2c37SJose E. Roman #endif
10166c0f0dcc3SMatthew G. Knepley 
10167c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
10168c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10169c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
101709566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
101719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
101729566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
101739566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
101749566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
101759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
101769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
10177c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart) * Nf * eventInfo.count;
10178c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops / eventInfo.time;
10179c0f0dcc3SMatthew G. Knepley   cellRate = N / eventInfo.time;
1018063a3b9bcSJacob 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)));
10181c0f0dcc3SMatthew G. Knepley #else
10182c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
10183c0f0dcc3SMatthew G. Knepley #endif
101843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10185c0f0dcc3SMatthew G. Knepley }
10186