xref: /petsc/src/dm/impls/plex/plex.c (revision 46139095832dbec5bd83c8636886c7e9bb646aaf)
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;
14*46139095SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate;
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 
33a1cb98faSBarry Smith .seealso: [](chapter_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;
449371c9d4SSatish Balay     PetscFunctionReturn(0);
459371c9d4SSatish Balay   }
469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
479318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
489318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
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 
67a1cb98faSBarry Smith .seealso: [](chapter_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;
105e5337592SStefano Zampini   PetscFunctionReturn(0);
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   }
1269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_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   }
1477e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
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 
1536913077dSMatthew G. Knepley   Collective on dm
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 
163a1cb98faSBarry Smith .seealso: [](chapter_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));
1846913077dSMatthew G. Knepley   if (!draw) PetscFunctionReturn(0);
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));
2019566063dSJacob Faibussowitsch         PetscCall(PetscStrcpy(tmpname, vname));
2029566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN));
2039566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN));
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));
2316913077dSMatthew G. Knepley   PetscFunctionReturn(0);
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));
2416913077dSMatthew G. Knepley   PetscFunctionReturn(0);
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;
252e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
253e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
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));
2779566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
278e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
2799371c9d4SSatish Balay     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));
2809371c9d4SSatish Balay     bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
2819371c9d4SSatish Balay     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1]));
2829371c9d4SSatish Balay     bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1]));
283e412dcbdSMatthew G. Knepley   }
2849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2859566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
286e412dcbdSMatthew G. Knepley 
287d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
288d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
289d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
290d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
291d1df6f1dSMatthew G. Knepley     IS          fis;
292d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
293d1df6f1dSMatthew G. Knepley     const char *fname;
294d1df6f1dSMatthew G. Knepley 
2959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
297d1df6f1dSMatthew G. Knepley 
2989566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
299ad540459SPierre Jolivet     else prefix[0] = '\0';
300d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3019566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
3029566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
3039566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
3049566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
305d1df6f1dSMatthew G. Knepley     }
306d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
307d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
308d1df6f1dSMatthew G. Knepley 
3099566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
31063a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
31163a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
3129566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
313d1df6f1dSMatthew G. Knepley 
314d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
316339e3443SMatthew G. Knepley       if (!flg) {
3179566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
3189566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
319d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
320339e3443SMatthew G. Knepley       }
3219566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
3229566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
3239566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]));
324e412dcbdSMatthew G. Knepley 
3259566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
326e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
32799a2f7bcSMatthew G. Knepley         PetscScalar *coords = NULL, *a   = NULL;
328e56f9228SJed Brown         PetscInt     numCoords, color[4] = {-1, -1, -1, -1};
329e412dcbdSMatthew G. Knepley 
3309566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
331339e3443SMatthew G. Knepley         if (a) {
332d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
333339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
334339e3443SMatthew G. Knepley         } else {
335339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
336339e3443SMatthew G. Knepley           PetscInt     numVals, va;
337339e3443SMatthew G. Knepley 
3389566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
33963a3b9bcSJacob 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);
340d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
341d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
342d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
343d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
344339e3443SMatthew G. Knepley             break;
345d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
346d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
347d1df6f1dSMatthew 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]);
348d1df6f1dSMatthew G. Knepley             break;
349d71ae5a4SJacob Faibussowitsch           default:
350d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
351339e3443SMatthew G. Knepley           }
3529566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
353339e3443SMatthew G. Knepley         }
3549566063dSJacob Faibussowitsch         PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
355e412dcbdSMatthew G. Knepley         switch (numCoords) {
356e412dcbdSMatthew G. Knepley         case 6:
3579edc3542SMatthew Knepley         case 12: /* Localized triangle */
3589566063dSJacob 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]));
359e412dcbdSMatthew G. Knepley           break;
360e412dcbdSMatthew G. Knepley         case 8:
3619edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
3629566063dSJacob 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]));
3639566063dSJacob 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]));
364e412dcbdSMatthew G. Knepley           break;
365d71ae5a4SJacob Faibussowitsch         default:
366d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
367e412dcbdSMatthew G. Knepley         }
3689566063dSJacob Faibussowitsch         PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
369e412dcbdSMatthew G. Knepley       }
3709566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
3719566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
3729566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
3739566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
374d1df6f1dSMatthew G. Knepley     }
375d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3769566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
3779566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
3789566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
379d1df6f1dSMatthew G. Knepley     }
380d1df6f1dSMatthew G. Knepley   }
381e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
382e412dcbdSMatthew G. Knepley }
383e412dcbdSMatthew G. Knepley 
384d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
385d71ae5a4SJacob Faibussowitsch {
3866913077dSMatthew G. Knepley   DM        dm;
3876913077dSMatthew G. Knepley   PetscDraw draw;
3886913077dSMatthew G. Knepley   PetscInt  dim;
3896913077dSMatthew G. Knepley   PetscBool isnull;
3906913077dSMatthew G. Knepley 
3916913077dSMatthew G. Knepley   PetscFunctionBegin;
3929566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3939566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
3946913077dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
3956913077dSMatthew G. Knepley 
3969566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3986913077dSMatthew G. Knepley   switch (dim) {
399d71ae5a4SJacob Faibussowitsch   case 1:
400d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
401d71ae5a4SJacob Faibussowitsch     break;
402d71ae5a4SJacob Faibussowitsch   case 2:
403d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
404d71ae5a4SJacob Faibussowitsch     break;
405d71ae5a4SJacob Faibussowitsch   default:
406d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
4076913077dSMatthew G. Knepley   }
4086913077dSMatthew G. Knepley   PetscFunctionReturn(0);
4096913077dSMatthew G. Knepley }
4106913077dSMatthew G. Knepley 
411d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
412d71ae5a4SJacob Faibussowitsch {
413684b87d9SLisandro Dalcin   DM                      dm;
414684b87d9SLisandro Dalcin   Vec                     locv;
415684b87d9SLisandro Dalcin   const char             *name;
416684b87d9SLisandro Dalcin   PetscSection            section;
417684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
418e630c359SToby Isaac   PetscInt                numFields;
419684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
420684b87d9SLisandro Dalcin 
421684b87d9SLisandro Dalcin   PetscFunctionBegin;
4229566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4239566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4249566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
4259566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
4269566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4279566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
429e630c359SToby Isaac   if (!numFields) {
4309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4319566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
432e630c359SToby Isaac   } else {
433e630c359SToby Isaac     PetscInt f;
434e630c359SToby Isaac 
435e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
437e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4389566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4399566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
440e630c359SToby Isaac     }
4419566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
442e630c359SToby Isaac   }
443684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
444684b87d9SLisandro Dalcin }
445684b87d9SLisandro Dalcin 
446d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
447d71ae5a4SJacob Faibussowitsch {
448552f7358SJed Brown   DM        dm;
4495f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
450552f7358SJed Brown 
451552f7358SJed Brown   PetscFunctionBegin;
4529566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
45328b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
4559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
4569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
4579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
4585f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
4595f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
460684b87d9SLisandro Dalcin     PetscInt    i, numFields;
461684b87d9SLisandro Dalcin     PetscObject fe;
462ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
463684b87d9SLisandro Dalcin     Vec         locv = v;
464684b87d9SLisandro Dalcin     const char *name;
465684b87d9SLisandro Dalcin     PetscInt    step;
466684b87d9SLisandro Dalcin     PetscReal   time;
467ef31f671SMatthew G. Knepley 
4689566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
469684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
4709566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
4719371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
4729371c9d4SSatish Balay         fem = PETSC_TRUE;
4739371c9d4SSatish Balay         break;
4749371c9d4SSatish Balay       }
475ef31f671SMatthew G. Knepley     }
476684b87d9SLisandro Dalcin     if (fem) {
477798534f6SMatthew G. Knepley       PetscObject isZero;
478798534f6SMatthew G. Knepley 
4799566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4809566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
4819566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
4829566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
4839566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
4849566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4859566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4869566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
487ef31f671SMatthew G. Knepley     }
488552f7358SJed Brown     if (isvtk) {
4899566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
490b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
491b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4929566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
493b136c2c9SMatthew G. Knepley #else
494b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
495b136c2c9SMatthew G. Knepley #endif
496f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4979566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
498684b87d9SLisandro Dalcin     } else if (isglvis) {
4999566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
5009566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
5019566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
5025f34f2dcSJed Brown     } else if (iscgns) {
5035f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
5045f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
5055f34f2dcSJed Brown #else
5065f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
5075f34f2dcSJed Brown #endif
508684b87d9SLisandro Dalcin     }
509798534f6SMatthew G. Knepley     if (fem) {
5109566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5119566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
512798534f6SMatthew G. Knepley     }
513552f7358SJed Brown   } else {
514684b87d9SLisandro Dalcin     PetscBool isseq;
515684b87d9SLisandro Dalcin 
5169566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5179566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5189566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
519552f7358SJed Brown   }
520552f7358SJed Brown   PetscFunctionReturn(0);
521552f7358SJed Brown }
522552f7358SJed Brown 
523d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
524d71ae5a4SJacob Faibussowitsch {
525552f7358SJed Brown   DM        dm;
5265f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
527552f7358SJed Brown 
528552f7358SJed Brown   PetscFunctionBegin;
5299566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
53028b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5355f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
5375f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
538552f7358SJed Brown     Vec         locv;
539798534f6SMatthew G. Knepley     PetscObject isZero;
540552f7358SJed Brown     const char *name;
541552f7358SJed Brown 
5429566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5439566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
5449566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
5459566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5469566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5479566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5489566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5499566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5509566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5519566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
552b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
553b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5549566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
555b136c2c9SMatthew G. Knepley #else
556b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
557b136c2c9SMatthew G. Knepley #endif
5586823f3c5SBlaise Bourdin   } else if (isexodusii) {
5596823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5609566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5616823f3c5SBlaise Bourdin #else
5626823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5636823f3c5SBlaise Bourdin #endif
564552f7358SJed Brown   } else {
565684b87d9SLisandro Dalcin     PetscBool isseq;
566684b87d9SLisandro Dalcin 
5679566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5689566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5699566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
570552f7358SJed Brown   }
571552f7358SJed Brown   PetscFunctionReturn(0);
572552f7358SJed Brown }
573552f7358SJed Brown 
574d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
575d71ae5a4SJacob Faibussowitsch {
576d930f514SMatthew G. Knepley   DM                dm;
577d930f514SMatthew G. Knepley   MPI_Comm          comm;
578d930f514SMatthew G. Knepley   PetscViewerFormat format;
579d930f514SMatthew G. Knepley   Vec               v;
580d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
581d930f514SMatthew G. Knepley 
582d930f514SMatthew G. Knepley   PetscFunctionBegin;
5839566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
58528b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5869566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
589d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
590a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
591a8ad634aSStefano Zampini     /* this need a better fix */
592a8ad634aSStefano Zampini     if (dm->useNatural) {
593a8ad634aSStefano Zampini       if (dm->sfNatural) {
594d930f514SMatthew G. Knepley         const char *vecname;
595d930f514SMatthew G. Knepley         PetscInt    n, nroots;
596d930f514SMatthew G. Knepley 
5979566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5989566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
599d930f514SMatthew G. Knepley         if (n == nroots) {
6009566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
6019566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
6029566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
6039566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
6049566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
605d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
606d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
607a8ad634aSStefano Zampini     } else v = originalv;
608a8ad634aSStefano Zampini   } else v = originalv;
609a8ad634aSStefano Zampini 
610d930f514SMatthew G. Knepley   if (ishdf5) {
611d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6129566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
613d930f514SMatthew G. Knepley #else
614d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
615d930f514SMatthew G. Knepley #endif
616d930f514SMatthew G. Knepley   } else if (isvtk) {
617d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
618d930f514SMatthew G. Knepley   } else {
619d930f514SMatthew G. Knepley     PetscBool isseq;
620d930f514SMatthew G. Knepley 
6219566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6229566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6239566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
624d930f514SMatthew G. Knepley   }
6259566063dSJacob Faibussowitsch   if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v));
626d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
627d930f514SMatthew G. Knepley }
628d930f514SMatthew G. Knepley 
629d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
630d71ae5a4SJacob Faibussowitsch {
6312c40f234SMatthew G. Knepley   DM        dm;
6322c40f234SMatthew G. Knepley   PetscBool ishdf5;
6332c40f234SMatthew G. Knepley 
6342c40f234SMatthew G. Knepley   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63628b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6382c40f234SMatthew G. Knepley   if (ishdf5) {
6392c40f234SMatthew G. Knepley     DM          dmBC;
6402c40f234SMatthew G. Knepley     Vec         gv;
6412c40f234SMatthew G. Knepley     const char *name;
6422c40f234SMatthew G. Knepley 
6439566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6449566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6459566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
6479566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6489566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6499566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6509566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6511baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6522c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
6532c40f234SMatthew G. Knepley }
6542c40f234SMatthew G. Knepley 
655d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
656d71ae5a4SJacob Faibussowitsch {
6572c40f234SMatthew G. Knepley   DM        dm;
6586823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
6592c40f234SMatthew G. Knepley 
6602c40f234SMatthew G. Knepley   PetscFunctionBegin;
6619566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
66228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6652c40f234SMatthew G. Knepley   if (ishdf5) {
666878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6679566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
668b136c2c9SMatthew G. Knepley #else
669b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
670878b459fSMatthew G. Knepley #endif
6716823f3c5SBlaise Bourdin   } else if (isexodusii) {
6726823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6739566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6746823f3c5SBlaise Bourdin #else
6756823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6766823f3c5SBlaise Bourdin #endif
6771baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
678552f7358SJed Brown   PetscFunctionReturn(0);
679552f7358SJed Brown }
680552f7358SJed Brown 
681d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
682d71ae5a4SJacob Faibussowitsch {
683d930f514SMatthew G. Knepley   DM                dm;
684d930f514SMatthew G. Knepley   PetscViewerFormat format;
685d930f514SMatthew G. Knepley   PetscBool         ishdf5;
686d930f514SMatthew G. Knepley 
687d930f514SMatthew G. Knepley   PetscFunctionBegin;
6889566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
68928b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6909566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
692d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
693a8ad634aSStefano Zampini     if (dm->useNatural) {
694d930f514SMatthew G. Knepley       if (dm->sfNatural) {
695d930f514SMatthew G. Knepley         if (ishdf5) {
696d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
697d930f514SMatthew G. Knepley           Vec         v;
698d930f514SMatthew G. Knepley           const char *vecname;
699d930f514SMatthew G. Knepley 
7009566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
7019566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7029566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
7039566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
7049566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
7059566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
7069566063dSJacob Faibussowitsch           PetscCall(DMRestoreGlobalVector(dm, &v));
707d930f514SMatthew G. Knepley #else
708d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
709d930f514SMatthew G. Knepley #endif
710d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
711d930f514SMatthew G. Knepley       }
7121baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
713d930f514SMatthew G. Knepley   }
714d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
715d930f514SMatthew G. Knepley }
716d930f514SMatthew G. Knepley 
717d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
718d71ae5a4SJacob Faibussowitsch {
719731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
720731e8ddeSMatthew G. Knepley   Vec                coordinates;
721ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
722731e8ddeSMatthew G. Knepley   const char        *name[4];
723731e8ddeSMatthew G. Knepley   const PetscScalar *a;
724731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
725731e8ddeSMatthew G. Knepley 
726731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7279566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7289566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7299566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
735731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
736731e8ddeSMatthew G. Knepley   name[1]       = "edge";
737731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
738731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
739731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
740731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
741ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
742731e8ddeSMatthew G. Knepley 
7439566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
74463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
747731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
748731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
749731e8ddeSMatthew G. Knepley 
750731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
752731e8ddeSMatthew G. Knepley       if (!dof) continue;
7539566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
75563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
756731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
7579566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
758731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7599566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7609566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
761731e8ddeSMatthew G. Knepley         }
7629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
763731e8ddeSMatthew G. Knepley       }
7649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
765731e8ddeSMatthew G. Knepley     }
7669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
768731e8ddeSMatthew G. Knepley   }
7699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
770731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
771731e8ddeSMatthew G. Knepley }
772731e8ddeSMatthew G. Knepley 
7739371c9d4SSatish Balay typedef enum {
7749371c9d4SSatish Balay   CS_CARTESIAN,
7759371c9d4SSatish Balay   CS_POLAR,
7769371c9d4SSatish Balay   CS_CYLINDRICAL,
7779371c9d4SSatish Balay   CS_SPHERICAL
7789371c9d4SSatish Balay } CoordSystem;
77919ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
78019ad8254SMatthew G. Knepley 
781d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
782d71ae5a4SJacob Faibussowitsch {
78319ad8254SMatthew G. Knepley   PetscInt i;
78419ad8254SMatthew G. Knepley 
78519ad8254SMatthew G. Knepley   PetscFunctionBegin;
78619ad8254SMatthew G. Knepley   if (dim > 3) {
7879566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
78819ad8254SMatthew G. Knepley   } else {
789bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
79019ad8254SMatthew G. Knepley 
79119ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
79219ad8254SMatthew G. Knepley     switch (cs) {
7939371c9d4SSatish Balay     case CS_CARTESIAN:
7949371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
7959371c9d4SSatish Balay       break;
79619ad8254SMatthew G. Knepley     case CS_POLAR:
79763a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 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       break;
80119ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
80263a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
80319ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
80419ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
80519ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
80619ad8254SMatthew G. Knepley       break;
80719ad8254SMatthew G. Knepley     case CS_SPHERICAL:
80863a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
80919ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
81019ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
81119ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
81219ad8254SMatthew G. Knepley       break;
81319ad8254SMatthew G. Knepley     }
8149566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
81519ad8254SMatthew G. Knepley   }
81619ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
81719ad8254SMatthew G. Knepley }
81819ad8254SMatthew G. Knepley 
819d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
820d71ae5a4SJacob Faibussowitsch {
821552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
8226858538eSMatthew G. Knepley   DM                cdm, cdmCell;
8236858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
8246858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
825552f7358SJed Brown   PetscViewerFormat format;
826552f7358SJed Brown 
827552f7358SJed Brown   PetscFunctionBegin;
8289566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
829552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
830552f7358SJed Brown     const char *name;
831f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8329318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
833552f7358SJed Brown     PetscMPIInt rank, size;
834552f7358SJed Brown 
8359f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
8369f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
8379f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8389f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
8399f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
8409f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
8419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8439566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
8449566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8469566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
84863a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
84963a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
85063a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
85163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
85363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
854552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
855552f7358SJed Brown       PetscInt dof, off, s;
856552f7358SJed Brown 
8579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
85948a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
860552f7358SJed Brown     }
8619566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
86263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
86363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
864552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
865552f7358SJed Brown       PetscInt dof, off, c;
866552f7358SJed Brown 
8679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
86948a46eb9SPierre 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]));
870552f7358SJed Brown     }
8719566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8733d2e540fSStefano Zampini     if (coordSection && coordinates) {
87419ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8756858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8766858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
87719ad8254SMatthew G. Knepley       PetscMPIInt        rank;
87819ad8254SMatthew G. Knepley       const char        *name;
87919ad8254SMatthew G. Knepley 
8809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
8819566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8829566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
88363a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8856858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8866858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8876858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
8886858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
8899566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
89063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
89163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
8929566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
89319ad8254SMatthew G. Knepley 
8949566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8956858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
8969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
89819ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
89919ad8254SMatthew G. Knepley         PetscInt dof, off;
90019ad8254SMatthew G. Knepley 
9016858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
9029566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
9039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
9046858538eSMatthew G. Knepley           if (dof) {
90563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
9069566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
9079566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
90819ad8254SMatthew G. Knepley           }
9096858538eSMatthew G. Knepley         }
9106858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
9116858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
9126858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
9136858538eSMatthew G. Knepley           if (dof) {
9146858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
9156858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
9166858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
9176858538eSMatthew G. Knepley           }
9186858538eSMatthew G. Knepley         }
9196858538eSMatthew G. Knepley       }
9209566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
9219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9229566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
9236858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
9243d2e540fSStefano Zampini     }
9259566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9269566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
9279318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
9289318fe57SMatthew G. Knepley       DMLabel     label;
9299318fe57SMatthew G. Knepley       PetscBool   isdepth;
9309318fe57SMatthew G. Knepley       const char *name;
9319318fe57SMatthew G. Knepley 
9329566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9339566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9349318fe57SMatthew G. Knepley       if (isdepth) continue;
9359566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9369566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9379318fe57SMatthew G. Knepley     }
938552f7358SJed Brown     if (size > 1) {
939552f7358SJed Brown       PetscSF sf;
940552f7358SJed Brown 
9419566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9429566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
943552f7358SJed Brown     }
9444e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
9459566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
946552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9470588280cSMatthew G. Knepley     const char  *name, *color;
9480588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9490588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
950fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
951552f7358SJed Brown     PetscReal    scale      = 2.0;
95278081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
953b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9540588280cSMatthew G. Knepley     double       tcoords[3];
955552f7358SJed Brown     PetscScalar *coords;
956b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
957552f7358SJed Brown     PetscMPIInt  rank, size;
9580588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
959b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
960fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
961fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
962552f7358SJed Brown 
9639f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9649f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9659f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9669f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9679f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9689f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9699566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9719566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9720588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9730588280cSMatthew G. Knepley     numColors  = 10;
9740588280cSMatthew G. Knepley     numLColors = 10;
9759566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9769566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
979b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
980b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
981b7f6ffafSMatthew G. Knepley     n = 4;
9829566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9831dca8a05SBarry 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);
9849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9851dca8a05SBarry 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);
9869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9870588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9890588280cSMatthew G. Knepley     if (!useColors) {
9900588280cSMatthew G. Knepley       numColors = 3;
9919566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9920588280cSMatthew G. Knepley     }
9939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9940588280cSMatthew G. Knepley     if (!useColors) {
9950588280cSMatthew G. Knepley       numLColors = 4;
9969566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9970588280cSMatthew G. Knepley     }
9989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
999b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
10009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
10011dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1002202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
10039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1004fe1cc32dSStefano Zampini 
1005fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
10069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
10079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
10089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
10099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1010fe1cc32dSStefano Zampini     if (lflg) {
1011fe1cc32dSStefano Zampini       DMLabel lbl;
1012fe1cc32dSStefano Zampini 
10139566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1014fe1cc32dSStefano Zampini       if (lbl) {
1015fe1cc32dSStefano Zampini         PetscInt val, defval;
1016fe1cc32dSStefano Zampini 
10179566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
10189566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1019fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1020fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1021fe1cc32dSStefano Zampini           PetscInt  closureSize;
1022fe1cc32dSStefano Zampini 
10239566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1024fe1cc32dSStefano Zampini           if (val == defval) continue;
1025fe1cc32dSStefano Zampini 
10269566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
102748a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
10289566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1029fe1cc32dSStefano Zampini         }
1030fe1cc32dSStefano Zampini       }
1031fe1cc32dSStefano Zampini     }
1032fe1cc32dSStefano Zampini 
10339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
10369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10370588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1038552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1039552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1040552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10415f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10420588280cSMatthew G. Knepley     if (size > 1) {
10439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1044770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
104563a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
104663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1047770b213bSMatthew G Knepley       }
10489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10490588280cSMatthew G. Knepley     }
1050b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1051b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1052b7f6ffafSMatthew G. Knepley 
105363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
105463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
105563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
10569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
105763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
105863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
10599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
106063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
106163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
106263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
106363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
10649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1065b7f6ffafSMatthew G. Knepley     }
10669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1067fe1cc32dSStefano Zampini 
1068552f7358SJed Brown     /* Plot vertices */
10699566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1071552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1072552f7358SJed Brown       PetscInt  off, dof, d;
10730588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1074552f7358SJed Brown 
1075fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
10769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10789566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
107963a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
10800588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10810588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1082c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10830588280cSMatthew G. Knepley       }
10840588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10859371c9d4SSatish Balay       if (dim == 3) {
10869371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
10879371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
10889371c9d4SSatish Balay         tcoords[2]    = -tmp;
10899371c9d4SSatish Balay       }
1090552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10919566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10929566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1093552f7358SJed Brown       }
1094b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1095b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
10960588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10970588280cSMatthew G. Knepley         PetscInt val;
10989566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10999371c9d4SSatish Balay         if (val >= 0) {
11009371c9d4SSatish Balay           color     = lcolors[l % numLColors];
11019371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
11029371c9d4SSatish Balay           break;
11039371c9d4SSatish Balay         }
11040588280cSMatthew G. Knepley       }
1105b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
110663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1107b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
110863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
11091baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1110552f7358SJed Brown     }
11119566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
11129566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1113b7f6ffafSMatthew G. Knepley     /* Plot edges */
1114b7f6ffafSMatthew G. Knepley     if (plotEdges) {
11159566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
11169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1117b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1118b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1119b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1120b7f6ffafSMatthew G. Knepley 
1121b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
11229566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
112363a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
11249566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
11259566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
11269566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
11279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
11289566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1129b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1130b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1131b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1132b7f6ffafSMatthew G. Knepley         }
1133b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
11349371c9d4SSatish Balay         if (dim == 3) {
11359371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
11369371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
11379371c9d4SSatish Balay           tcoords[2]    = -tmp;
11389371c9d4SSatish Balay         }
1139b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11409566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11419566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1142b7f6ffafSMatthew G. Knepley         }
1143b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1144b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1145b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1146b7f6ffafSMatthew G. Knepley           PetscInt val;
11479566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
11489371c9d4SSatish Balay           if (val >= 0) {
11499371c9d4SSatish Balay             color = lcolors[l % numLColors];
11509371c9d4SSatish Balay             break;
11519371c9d4SSatish Balay           }
1152b7f6ffafSMatthew G. Knepley         }
115363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1154b7f6ffafSMatthew G. Knepley       }
11559566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11569566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1158b7f6ffafSMatthew G. Knepley     }
1159846a3e8bSMatthew G. Knepley     /* Plot cells */
1160b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1161846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1162846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1163846a3e8bSMatthew G. Knepley 
1164fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1165846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1166846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1167846a3e8bSMatthew G. Knepley           PetscInt val;
11689566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
11699371c9d4SSatish Balay           if (val >= 0) {
11709371c9d4SSatish Balay             color = lcolors[l % numLColors];
11719371c9d4SSatish Balay             break;
11729371c9d4SSatish Balay           }
1173846a3e8bSMatthew G. Knepley         }
11749566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
117563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1176846a3e8bSMatthew G. Knepley       }
1177846a3e8bSMatthew G. Knepley     } else {
1178b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1179846a3e8bSMatthew G. Knepley 
1180b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1181b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1182fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11839566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
11849371c9d4SSatish Balay         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1185b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1186b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1187b7f6ffafSMatthew G. Knepley 
11889566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11899566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1190b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1191b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1192b7f6ffafSMatthew G. Knepley 
11939566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
119463a3b9bcSJacob 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));
1195b7f6ffafSMatthew G. Knepley           }
1196b7f6ffafSMatthew G. Knepley         } else {
1197b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1198b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1199b7f6ffafSMatthew G. Knepley 
12009566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1201846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1202846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1203846a3e8bSMatthew G. Knepley 
1204b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1205846a3e8bSMatthew G. Knepley           }
12069566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1207b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1208b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1209b7f6ffafSMatthew G. Knepley 
1210b7f6ffafSMatthew G. Knepley             if (v > 0) {
1211b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1212b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1213b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1214b7f6ffafSMatthew G. Knepley 
12159371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
12169371c9d4SSatish Balay                 endpoints[1] = vertex;
12179566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
121863a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
121963a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
12209566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
12211baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1222b7f6ffafSMatthew G. Knepley             }
122363a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1224b7f6ffafSMatthew G. Knepley           }
12259566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
12269566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1227846a3e8bSMatthew G. Knepley         }
1228846a3e8bSMatthew G. Knepley       }
1229b7f6ffafSMatthew G. Knepley     }
1230846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1231846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1232846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1233c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1234c713ec31SMatthew G. Knepley       const PetscScalar *array;
1235c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1236c713ec31SMatthew G. Knepley       PetscBool          isDG;
1237846a3e8bSMatthew G. Knepley 
1238fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1239c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1240c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1241c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
12429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1243c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1244c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1245c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1246846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1247846a3e8bSMatthew G. Knepley         }
1248846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12499371c9d4SSatish Balay         if (cdim == 3) {
12509371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12519371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12529371c9d4SSatish Balay           tcoords[2]    = -tmp;
12539371c9d4SSatish Balay         }
1254ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1255846a3e8bSMatthew G. Knepley       }
1256ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1257c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1258c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
12599566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12609566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1261846a3e8bSMatthew G. Knepley       }
1262b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1263b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1264846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1265846a3e8bSMatthew G. Knepley         PetscInt val;
12669566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
12679371c9d4SSatish Balay         if (val >= 0) {
12689371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12699371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12709371c9d4SSatish Balay           break;
12719371c9d4SSatish Balay         }
1272846a3e8bSMatthew G. Knepley       }
1273b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
127463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1275b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
127663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12771baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1278846a3e8bSMatthew G. Knepley     }
1279b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1280b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
12819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1286552f7358SJed Brown 
1287b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
12889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1293b7f6ffafSMatthew G. Knepley 
1294b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
12959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1300b7f6ffafSMatthew G. Knepley 
1301b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1302b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1303b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1304b7f6ffafSMatthew G. Knepley 
13059566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
13069566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
130748a46eb9SPierre 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));
13080588280cSMatthew G. Knepley       }
13090588280cSMatthew G. Knepley     }
13109566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
13119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
13129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
131363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
13149566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
13159566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
13169566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
13179566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
13189566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
13190f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
13200f7d6e4aSStefano Zampini     Vec                    cown, acown;
13210f7d6e4aSStefano Zampini     VecScatter             sct;
13220f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
13230f7d6e4aSStefano Zampini     IS                     gid, acis;
13240f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
13250f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
13260f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
13270f7d6e4aSStefano Zampini     const PetscInt        *idxs;
13280f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
13290f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
13300f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
13310f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
13320f7d6e4aSStefano Zampini 
13339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
13349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1335b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
13369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
13370f7d6e4aSStefano Zampini #endif
13380f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
13399566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
13409566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
13410f7d6e4aSStefano Zampini       d1 = 0;
13429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
13430f7d6e4aSStefano Zampini       nid = d2;
13449566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
13459566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
13469566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
13470f7d6e4aSStefano Zampini     } else nid = 0.0;
13480f7d6e4aSStefano Zampini 
13490f7d6e4aSStefano Zampini     /* Get connectivity */
13509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13519566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
13520f7d6e4aSStefano Zampini 
13530f7d6e4aSStefano Zampini     /* filter overlapped local cells */
13549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
13559566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
13569566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
13579566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
13580f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13590f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
13600f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
13610f7d6e4aSStefano Zampini     }
13629566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
136363a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
13649566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13659566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
13660f7d6e4aSStefano Zampini 
13670f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13689566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
13699566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
13709566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
13719566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
13720f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
13749566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
13759566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13769566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13779566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13789566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13799566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13800f7d6e4aSStefano Zampini 
13810f7d6e4aSStefano Zampini     /* compute edgeCut */
13820f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
13839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
13849566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
13859566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
13869566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13879566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
13880f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13890f7d6e4aSStefano Zampini       PetscInt totl;
13900f7d6e4aSStefano Zampini 
13910f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
13929566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
13930f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13940f7d6e4aSStefano Zampini         if (work[i] < 0) {
13950f7d6e4aSStefano Zampini           ect += 1;
13960f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13970f7d6e4aSStefano Zampini         }
13980f7d6e4aSStefano Zampini       }
13990f7d6e4aSStefano Zampini     }
14009566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
14019566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
14020f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
14030f7d6e4aSStefano Zampini     lm[1] = -numVertices;
14041c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
140563a3b9bcSJacob 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]));
14060f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
14070f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
14080f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
14091c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
141063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1411b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
141263a3b9bcSJacob 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.));
14130f7d6e4aSStefano Zampini #else
141463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
14150f7d6e4aSStefano Zampini #endif
14169566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
14179566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
14189566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
14199566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1420552f7358SJed Brown   } else {
1421412e9a14SMatthew G. Knepley     const char    *name;
1422d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1423412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1424d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1425ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
14269318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1427412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1428412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1429552f7358SJed Brown 
14309566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
14329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
14339566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
14349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
143663a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
143763a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
143863a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
14399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
14401c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
14419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1442d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
14439566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
14449566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1445412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1446412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1447412e9a14SMatthew G. Knepley 
14489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
14499566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1450412e9a14SMatthew G. Knepley       ict = ct0;
14519566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1452412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1453412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1454412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1455412e9a14SMatthew G. Knepley 
14569566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1457412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1458412e9a14SMatthew G. Knepley         else ++Nc[1];
1459412e9a14SMatthew G. Knepley       }
1460ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14619566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
14629566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14639566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
146463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1465834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1466dd400576SPatrick Sanan           if (rank == 0) {
146763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
146863a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
146963a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1470834065abSMatthew G. Knepley           }
1471cbb7f117SMark Adams         }
1472ca7bf7eeSMatthew G. Knepley       } else {
1473ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1474ca7bf7eeSMatthew G. Knepley 
14759371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
14769371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
14779566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
14789371c9d4SSatish Balay         locMinMax[0] = Nc[1];
14799371c9d4SSatish Balay         locMinMax[1] = Nc[1];
14809566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1481ca7bf7eeSMatthew G. Knepley         if (d == depth) {
14829371c9d4SSatish Balay           locMinMax[0] = gcNum;
14839371c9d4SSatish Balay           locMinMax[1] = gcNum;
14849566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1485ca7bf7eeSMatthew G. Knepley         }
148663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14879566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14889566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14899566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1490ca7bf7eeSMatthew G. Knepley       }
14919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1492552f7358SJed Brown     }
14939566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14949318fe57SMatthew G. Knepley     {
14959318fe57SMatthew G. Knepley       const PetscReal *maxCell;
14969318fe57SMatthew G. Knepley       const PetscReal *L;
14976858538eSMatthew G. Knepley       PetscBool        localized;
14989318fe57SMatthew G. Knepley 
14994fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
15009566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
15016858538eSMatthew G. Knepley       if (L || localized) {
15026858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
15039566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
15046858538eSMatthew G. Knepley         if (L) {
15056858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
15069318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
15076858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
15086858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
15099318fe57SMatthew G. Knepley           }
15106858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
15116858538eSMatthew G. Knepley         }
15126858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
15139566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15149318fe57SMatthew G. Knepley       }
15159318fe57SMatthew G. Knepley     }
15169566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
15179566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1518a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1519a57dd577SMatthew G Knepley       DMLabel         label;
1520a57dd577SMatthew G Knepley       const char     *name;
1521a57dd577SMatthew G Knepley       IS              valueIS;
1522a57dd577SMatthew G Knepley       const PetscInt *values;
1523a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1524a57dd577SMatthew G Knepley 
15259566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
15269566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
15279566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
152863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
15299566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
15309566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
15319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1532a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1533a57dd577SMatthew G Knepley         PetscInt size;
1534a57dd577SMatthew G Knepley 
15359566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
15369566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
153763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1538a57dd577SMatthew G Knepley       }
15399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
15409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15419566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
15429566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1543a57dd577SMatthew G Knepley     }
1544c1cad2e7SMatthew G. Knepley     {
1545c1cad2e7SMatthew G. Knepley       char    **labelNames;
1546c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1547c1cad2e7SMatthew G. Knepley       PetscBool flg;
1548c1cad2e7SMatthew G. Knepley 
15499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
15509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1551c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1552c1cad2e7SMatthew G. Knepley         DMLabel label;
1553c1cad2e7SMatthew G. Knepley 
15549566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1555c1cad2e7SMatthew G. Knepley         if (flg) {
15569566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
15579566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1558c1cad2e7SMatthew G. Knepley         }
15599566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1560c1cad2e7SMatthew G. Knepley       }
15619566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1562c1cad2e7SMatthew G. Knepley     }
156334aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
156434aa8a36SMatthew G. Knepley     if (dm->Nf) {
156534aa8a36SMatthew G. Knepley       PetscInt f;
156634aa8a36SMatthew G. Knepley 
156734aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
156834aa8a36SMatthew G. Knepley         const char *name;
156934aa8a36SMatthew G. Knepley 
15709566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15719566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15729566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15739566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
157434aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15759566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15769566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
157734aa8a36SMatthew G. Knepley         } else {
15789566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15799566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
158034aa8a36SMatthew G. Knepley         }
15819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
158234aa8a36SMatthew G. Knepley       }
158334aa8a36SMatthew G. Knepley     }
15849566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15858e7ff633SMatthew G. Knepley     if (cdm) {
15869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15879f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
15889566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15908e7ff633SMatthew G. Knepley     }
1591552f7358SJed Brown   }
1592552f7358SJed Brown   PetscFunctionReturn(0);
1593552f7358SJed Brown }
1594552f7358SJed Brown 
1595d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1596d71ae5a4SJacob Faibussowitsch {
1597e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1598e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1599a12d352dSMatthew G. Knepley   PetscInt       cdim;
1600e5c487bfSMatthew G. Knepley 
1601e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
16039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
16049566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1605e5c487bfSMatthew G. Knepley   switch (ct) {
1606a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1607a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1608a12d352dSMatthew G. Knepley     switch (cdim) {
16099371c9d4SSatish Balay     case 1: {
1610a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1611a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1612a12d352dSMatthew G. Knepley 
16139566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
16149566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
16159566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
16169371c9d4SSatish Balay     } break;
16179371c9d4SSatish Balay     case 2: {
1618a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1619a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1620a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1621a12d352dSMatthew G. Knepley 
16229566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16239566063dSJacob 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));
16249566063dSJacob 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));
16259371c9d4SSatish Balay     } break;
1626d71ae5a4SJacob Faibussowitsch     default:
1627d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1628a12d352dSMatthew G. Knepley     }
1629a12d352dSMatthew G. Knepley     break;
1630e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
16319371c9d4SSatish 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));
16329566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16339566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16349566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1635e5c487bfSMatthew G. Knepley     break;
1636e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
16379371c9d4SSatish 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));
16389371c9d4SSatish 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));
16399566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16409566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16419566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1643e5c487bfSMatthew G. Knepley     break;
16449f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
16459f4ada15SMatthew 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));
16469f4ada15SMatthew 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));
16479f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16489f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16499f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16509f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
16519f4ada15SMatthew G. Knepley     break;
1652d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1653d71ae5a4SJacob Faibussowitsch     break;
1654d71ae5a4SJacob Faibussowitsch   default:
1655d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1656e5c487bfSMatthew G. Knepley   }
1657e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1658e5c487bfSMatthew G. Knepley }
1659e5c487bfSMatthew G. Knepley 
1660d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1661d71ae5a4SJacob Faibussowitsch {
1662e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1663e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1664e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1665e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1666e5c487bfSMatthew G. Knepley 
1667e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
16699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1670e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1671e5c487bfSMatthew G. Knepley   switch (ct) {
16729371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
1673e5c487bfSMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1674e5c487bfSMatthew G. Knepley 
16759371c9d4SSatish Balay     for (v = 0; v < 3; ++v) {
16769371c9d4SSatish Balay       centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.;
16779371c9d4SSatish Balay       centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.;
16789371c9d4SSatish Balay     }
1679e5c487bfSMatthew G. Knepley     for (e = 0; e < 3; ++e) {
1680e5c487bfSMatthew G. Knepley       refCoords[0] = refVertices[e * 2 + 0];
1681e5c487bfSMatthew G. Knepley       refCoords[1] = refVertices[e * 2 + 1];
1682e5c487bfSMatthew G. Knepley       for (d = 1; d <= edgeDiv; ++d) {
1683e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv;
1684e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv;
1685e5c487bfSMatthew G. Knepley       }
16869566063dSJacob Faibussowitsch       PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1687e5c487bfSMatthew G. Knepley       for (d = 0; d < edgeDiv; ++d) {
16889566063dSJacob 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));
16899566063dSJacob 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));
1690e5c487bfSMatthew G. Knepley       }
1691e5c487bfSMatthew G. Knepley     }
16929371c9d4SSatish Balay   } break;
1693d71ae5a4SJacob Faibussowitsch   default:
1694d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1695e5c487bfSMatthew G. Knepley   }
1696e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1697e5c487bfSMatthew G. Knepley }
1698e5c487bfSMatthew G. Knepley 
1699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1700d71ae5a4SJacob Faibussowitsch {
1701e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1702e412dcbdSMatthew G. Knepley   DM                 cdm;
1703e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1704e412dcbdSMatthew G. Knepley   Vec                coordinates;
1705e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
170629494db1SLisandro Dalcin   PetscReal          xyl[2], xyr[2], bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1707e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1708e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1709e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1710e412dcbdSMatthew G. Knepley 
1711e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
17129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
171363a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
17149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
17159566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
17169566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
17179566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
17189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
17199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1721e412dcbdSMatthew G. Knepley 
17229566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
17239566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1724e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
17259566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1726e412dcbdSMatthew G. Knepley 
17279566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
17289566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1729e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
17309371c9d4SSatish Balay     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));
17319371c9d4SSatish Balay     bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
17329371c9d4SSatish Balay     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1]));
17339371c9d4SSatish Balay     bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1]));
1734e412dcbdSMatthew G. Knepley   }
17359566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
17361c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[0], xyl, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm)));
17371c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[2], xyr, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
17389566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
17399566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1740e412dcbdSMatthew G. Knepley 
1741cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1742cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1743ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1744cf3064d3SMatthew G. Knepley 
17459566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
17461baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
17471baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
17489566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1749cf3064d3SMatthew G. Knepley   }
17509566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
17519566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
17529566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
17539566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1754e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1755e412dcbdSMatthew G. Knepley }
1756e412dcbdSMatthew G. Knepley 
17571e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17581e50132fSMatthew G. Knepley   #include <exodusII.h>
17596823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
17601e50132fSMatthew G. Knepley #endif
17611e50132fSMatthew G. Knepley 
1762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1763d71ae5a4SJacob Faibussowitsch {
17645f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1765002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1766552f7358SJed Brown 
1767552f7358SJed Brown   PetscFunctionBegin;
1768552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1769552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
17765f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1777552f7358SJed Brown   if (iascii) {
17788135c375SStefano Zampini     PetscViewerFormat format;
17799566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17801baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17811baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1782c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1783c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17849566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1785c6ccd67eSMatthew G. Knepley #else
1786c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1787552f7358SJed Brown #endif
1788e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17899566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1790e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17919566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17928135c375SStefano Zampini   } else if (isglvis) {
17939566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17941e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17951e50132fSMatthew G. Knepley   } else if (isexodus) {
17966823f3c5SBlaise Bourdin     /*
17976823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17986823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
17996823f3c5SBlaise Bourdin       with ID 1, containig all cells.
18006823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
18016823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
18026823f3c5SBlaise Bourdin     */
18036823f3c5SBlaise Bourdin     PetscInt numCS;
18049566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
18056823f3c5SBlaise Bourdin     if (!numCS) {
18061e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
18079566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
18089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
18099566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
18106823f3c5SBlaise Bourdin     }
18119566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
18121e50132fSMatthew G. Knepley #endif
18135f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
18145f34f2dcSJed Brown   } else if (iscgns) {
18155f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
18165f34f2dcSJed Brown #endif
18171baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1818cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
18199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1820cb3ba0daSMatthew G. Knepley   if (flg) {
1821cb3ba0daSMatthew G. Knepley     Vec ranks;
18229566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
18239566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
18249566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1825cb3ba0daSMatthew G. Knepley   }
1826002a2709SMatthew G. Knepley   /* Optionally view a label */
18279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1828002a2709SMatthew G. Knepley   if (flg) {
1829002a2709SMatthew G. Knepley     DMLabel label;
1830002a2709SMatthew G. Knepley     Vec     val;
1831002a2709SMatthew G. Knepley 
18329566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
183328b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
18349566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
18359566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
18369566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1837002a2709SMatthew G. Knepley   }
1838552f7358SJed Brown   PetscFunctionReturn(0);
1839552f7358SJed Brown }
1840552f7358SJed Brown 
18417f96f51bSksagiyam /*@
1842a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
18437f96f51bSksagiyam 
1844a1cb98faSBarry Smith   Collective on dm
18457f96f51bSksagiyam 
18467f96f51bSksagiyam   Input Parameters:
1847a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
1848a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
18497f96f51bSksagiyam 
18507f96f51bSksagiyam   Level: advanced
18517f96f51bSksagiyam 
1852a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
18537f96f51bSksagiyam @*/
1854d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
1855d71ae5a4SJacob Faibussowitsch {
18567f96f51bSksagiyam   PetscBool ishdf5;
18577f96f51bSksagiyam 
18587f96f51bSksagiyam   PetscFunctionBegin;
18597f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18607f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
18637f96f51bSksagiyam   if (ishdf5) {
18647f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
18657f96f51bSksagiyam     PetscViewerFormat format;
18669566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18677f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18687f96f51bSksagiyam       IS globalPointNumbering;
18697f96f51bSksagiyam 
18709566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18719566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18729566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
187398921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18747f96f51bSksagiyam #else
18757f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18767f96f51bSksagiyam #endif
18777f96f51bSksagiyam   }
18789566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
18797f96f51bSksagiyam   PetscFunctionReturn(0);
18807f96f51bSksagiyam }
18817f96f51bSksagiyam 
188277b8e257Sksagiyam /*@
1883a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
188477b8e257Sksagiyam 
1885a1cb98faSBarry Smith   Collective on dm
188677b8e257Sksagiyam 
188777b8e257Sksagiyam   Input Parameters:
1888a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
1889a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
189077b8e257Sksagiyam 
189177b8e257Sksagiyam   Level: advanced
189277b8e257Sksagiyam 
1893a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
189477b8e257Sksagiyam @*/
1895d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
1896d71ae5a4SJacob Faibussowitsch {
189777b8e257Sksagiyam   PetscBool ishdf5;
189877b8e257Sksagiyam 
189977b8e257Sksagiyam   PetscFunctionBegin;
190077b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
190177b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
190477b8e257Sksagiyam   if (ishdf5) {
190577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
190677b8e257Sksagiyam     PetscViewerFormat format;
19079566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
190877b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
19099566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
1910fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
191177b8e257Sksagiyam #else
191277b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
191377b8e257Sksagiyam #endif
191477b8e257Sksagiyam   }
19159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
191677b8e257Sksagiyam   PetscFunctionReturn(0);
191777b8e257Sksagiyam }
191877b8e257Sksagiyam 
1919bd6565f1Sksagiyam /*@
1920a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
1921bd6565f1Sksagiyam 
1922a1cb98faSBarry Smith   Collective on dm
1923bd6565f1Sksagiyam 
1924bd6565f1Sksagiyam   Input Parameters:
1925a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
1926a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
1927bd6565f1Sksagiyam 
1928bd6565f1Sksagiyam   Level: advanced
1929bd6565f1Sksagiyam 
1930a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
1931bd6565f1Sksagiyam @*/
1932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1933d71ae5a4SJacob Faibussowitsch {
1934bd6565f1Sksagiyam   PetscBool ishdf5;
1935bd6565f1Sksagiyam 
1936bd6565f1Sksagiyam   PetscFunctionBegin;
1937bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1938bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
1941bd6565f1Sksagiyam   if (ishdf5) {
1942bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1943bd6565f1Sksagiyam     IS                globalPointNumbering;
1944bd6565f1Sksagiyam     PetscViewerFormat format;
1945bd6565f1Sksagiyam 
19469566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1947bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
19489566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
19499566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
19509566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
195198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1952bd6565f1Sksagiyam #else
1953bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1954bd6565f1Sksagiyam #endif
1955bd6565f1Sksagiyam   }
19569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
1957bd6565f1Sksagiyam   PetscFunctionReturn(0);
1958bd6565f1Sksagiyam }
1959bd6565f1Sksagiyam 
1960021affd3Sksagiyam /*@
1961a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
1962021affd3Sksagiyam 
1963a1cb98faSBarry Smith   Collective on dm
1964021affd3Sksagiyam 
1965021affd3Sksagiyam   Input Parameters:
1966a1cb98faSBarry Smith + dm         - The `DM` that contains the topology on which the section to be saved is defined
1967a1cb98faSBarry Smith . viewer     - The `PetscViewer` for saving
1968a1cb98faSBarry Smith - sectiondm  - The `DM` that contains the section to be saved
1969021affd3Sksagiyam 
1970021affd3Sksagiyam   Level: advanced
1971021affd3Sksagiyam 
1972021affd3Sksagiyam   Notes:
1973a1cb98faSBarry 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.
1974021affd3Sksagiyam 
1975a1cb98faSBarry 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.
1976021affd3Sksagiyam 
1977a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
1978021affd3Sksagiyam @*/
1979d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1980d71ae5a4SJacob Faibussowitsch {
1981021affd3Sksagiyam   PetscBool ishdf5;
1982021affd3Sksagiyam 
1983021affd3Sksagiyam   PetscFunctionBegin;
1984021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1985021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1986021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
1989021affd3Sksagiyam   if (ishdf5) {
1990021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19919566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1992021affd3Sksagiyam #else
1993021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1994021affd3Sksagiyam #endif
1995021affd3Sksagiyam   }
19969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
1997021affd3Sksagiyam   PetscFunctionReturn(0);
1998021affd3Sksagiyam }
1999021affd3Sksagiyam 
20003e97647fSksagiyam /*@
20013e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
20023e97647fSksagiyam 
2003a1cb98faSBarry Smith   Collective on dm
20043e97647fSksagiyam 
20053e97647fSksagiyam   Input Parameters:
2006a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2007a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
2008a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
20093e97647fSksagiyam - vec       - The global vector to be saved
20103e97647fSksagiyam 
20113e97647fSksagiyam   Level: advanced
20123e97647fSksagiyam 
20133e97647fSksagiyam   Notes:
2014a1cb98faSBarry 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.
20153e97647fSksagiyam 
2016a1cb98faSBarry Smith   Typical calling sequence:
2017a1cb98faSBarry Smith .vb
2018a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2019a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2020a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2021a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2022a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2023a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2024a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2025a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2026a1cb98faSBarry Smith        PetscSectionSetUp(section);
2027a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2028a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2029a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2030a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2031a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2032a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2033a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2034a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2035a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2036a1cb98faSBarry Smith        DMDestroy(&dm);
2037a1cb98faSBarry Smith .ve
20383e97647fSksagiyam 
2039a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20403e97647fSksagiyam @*/
2041d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2042d71ae5a4SJacob Faibussowitsch {
20433e97647fSksagiyam   PetscBool ishdf5;
20443e97647fSksagiyam 
20453e97647fSksagiyam   PetscFunctionBegin;
20463e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20473e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20483e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20493e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20503e97647fSksagiyam   /* Check consistency */
20513e97647fSksagiyam   {
20523e97647fSksagiyam     PetscSection section;
20533e97647fSksagiyam     PetscBool    includesConstraints;
20543e97647fSksagiyam     PetscInt     m, m1;
20553e97647fSksagiyam 
20569566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20579566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
20589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20599566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20609566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
206163a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
20623e97647fSksagiyam   }
20639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20653e97647fSksagiyam   if (ishdf5) {
20663e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20679566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20683e97647fSksagiyam #else
20693e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20703e97647fSksagiyam #endif
20713e97647fSksagiyam   }
20729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20733e97647fSksagiyam   PetscFunctionReturn(0);
20743e97647fSksagiyam }
20753e97647fSksagiyam 
20763e97647fSksagiyam /*@
20773e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20783e97647fSksagiyam 
2079a1cb98faSBarry Smith   Collective on dm
20803e97647fSksagiyam 
20813e97647fSksagiyam   Input Parameters:
2082a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2083a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
2084a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined; may be the same as dm
20853e97647fSksagiyam - vec       - The local vector to be saved
20863e97647fSksagiyam 
20873e97647fSksagiyam   Level: advanced
20883e97647fSksagiyam 
2089a1cb98faSBarry Smith   Note:
2090a1cb98faSBarry 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.
20913e97647fSksagiyam 
2092a1cb98faSBarry Smith   Typical calling sequence:
2093a1cb98faSBarry Smith .vb
2094a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2095a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2096a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2097a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2098a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2099a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2100a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2101a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2102a1cb98faSBarry Smith        PetscSectionSetUp(section);
2103a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2104a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2105a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2106a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2107a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2108a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2109a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2110a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2111a1cb98faSBarry Smith        DMDestroy(&dm);
2112a1cb98faSBarry Smith .ve
21133e97647fSksagiyam 
2114a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
21153e97647fSksagiyam @*/
2116d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2117d71ae5a4SJacob Faibussowitsch {
21183e97647fSksagiyam   PetscBool ishdf5;
21193e97647fSksagiyam 
21203e97647fSksagiyam   PetscFunctionBegin;
21213e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21223e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21233e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21243e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
21253e97647fSksagiyam   /* Check consistency */
21263e97647fSksagiyam   {
21273e97647fSksagiyam     PetscSection section;
21283e97647fSksagiyam     PetscBool    includesConstraints;
21293e97647fSksagiyam     PetscInt     m, m1;
21303e97647fSksagiyam 
21319566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
21329566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
21339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
21349566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
21359566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
213663a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
21373e97647fSksagiyam   }
21389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
21403e97647fSksagiyam   if (ishdf5) {
21413e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
21429566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
21433e97647fSksagiyam #else
21443e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21453e97647fSksagiyam #endif
21463e97647fSksagiyam   }
21479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
21483e97647fSksagiyam   PetscFunctionReturn(0);
21493e97647fSksagiyam }
21503e97647fSksagiyam 
2151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2152d71ae5a4SJacob Faibussowitsch {
2153d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
21542c40f234SMatthew G. Knepley 
21552c40f234SMatthew G. Knepley   PetscFunctionBegin;
21562c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21572c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2159d4f5a9a0SVaclav Hapla   if (ishdf5) {
21602c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
21619c48423bSVaclav Hapla     PetscViewerFormat format;
21629566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21639c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
21649566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2165509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21669566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
216798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2168b458e8f1SJose E. Roman     PetscFunctionReturn(0);
21692c40f234SMatthew G. Knepley #else
21702c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2171552f7358SJed Brown #endif
217298921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2173552f7358SJed Brown }
2174552f7358SJed Brown 
2175ea8e1828Sksagiyam /*@
2176a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2177ea8e1828Sksagiyam 
2178a1cb98faSBarry Smith   Collective on dm
2179ea8e1828Sksagiyam 
2180ea8e1828Sksagiyam   Input Parameters:
2181a1cb98faSBarry Smith + dm                - The `DM` into which the topology is loaded
2182a1cb98faSBarry Smith - viewer            - The `PetscViewer` for the saved topology
2183ea8e1828Sksagiyam 
2184dec9e869Sksagiyam   Output Parameters:
2185a1cb98faSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded plex, where N is the global number of points; NULL if unneeded
2186dec9e869Sksagiyam 
2187ea8e1828Sksagiyam   Level: advanced
2188ea8e1828Sksagiyam 
2189a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2190a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2191ea8e1828Sksagiyam @*/
2192d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2193d71ae5a4SJacob Faibussowitsch {
2194ea8e1828Sksagiyam   PetscBool ishdf5;
2195ea8e1828Sksagiyam 
2196ea8e1828Sksagiyam   PetscFunctionBegin;
2197ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2198ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2199f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
22009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2202ea8e1828Sksagiyam   if (ishdf5) {
2203ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2204ea8e1828Sksagiyam     PetscViewerFormat format;
22059566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2206ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22079566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
220898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2209ea8e1828Sksagiyam #else
2210ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2211ea8e1828Sksagiyam #endif
2212ea8e1828Sksagiyam   }
22139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2214ea8e1828Sksagiyam   PetscFunctionReturn(0);
2215ea8e1828Sksagiyam }
2216ea8e1828Sksagiyam 
22173e701f1cSksagiyam /*@
2218a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
22193e701f1cSksagiyam 
2220a1cb98faSBarry Smith   Collective on dm
22213e701f1cSksagiyam 
22223e701f1cSksagiyam   Input Parameters:
2223a1cb98faSBarry Smith + dm     - The `DM` into which the coordinates are loaded
2224a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates
2225a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
22263e701f1cSksagiyam 
22273e701f1cSksagiyam   Level: advanced
22283e701f1cSksagiyam 
2229a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2230a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
22313e701f1cSksagiyam @*/
2232d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2233d71ae5a4SJacob Faibussowitsch {
22343e701f1cSksagiyam   PetscBool ishdf5;
22353e701f1cSksagiyam 
22363e701f1cSksagiyam   PetscFunctionBegin;
22373e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22383e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2239c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
22423e701f1cSksagiyam   if (ishdf5) {
22433e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
22443e701f1cSksagiyam     PetscViewerFormat format;
22459566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
22463e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22479566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
224898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
22493e701f1cSksagiyam #else
22503e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22513e701f1cSksagiyam #endif
22523e701f1cSksagiyam   }
22539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
22543e701f1cSksagiyam   PetscFunctionReturn(0);
22553e701f1cSksagiyam }
22563e701f1cSksagiyam 
2257b08ad5deSksagiyam /*@
2258a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2259b08ad5deSksagiyam 
2260a1cb98faSBarry Smith   Collective on dm
2261b08ad5deSksagiyam 
2262b08ad5deSksagiyam   Input Parameters:
2263a1cb98faSBarry Smith + dm     - The `DM` into which the labels are loaded
2264a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels
2265a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
2266b08ad5deSksagiyam 
2267b08ad5deSksagiyam   Level: advanced
2268b08ad5deSksagiyam 
2269a1cb98faSBarry Smith   Note:
2270a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2271e6368b79SVaclav Hapla 
2272a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2273a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2274b08ad5deSksagiyam @*/
2275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2276d71ae5a4SJacob Faibussowitsch {
2277b08ad5deSksagiyam   PetscBool ishdf5;
2278b08ad5deSksagiyam 
2279b08ad5deSksagiyam   PetscFunctionBegin;
2280b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2281b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2282e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2285b08ad5deSksagiyam   if (ishdf5) {
2286b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2287b08ad5deSksagiyam     PetscViewerFormat format;
2288b08ad5deSksagiyam 
22899566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2290b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22919566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
229298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2293b08ad5deSksagiyam #else
2294b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2295b08ad5deSksagiyam #endif
2296b08ad5deSksagiyam   }
22979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2298b08ad5deSksagiyam   PetscFunctionReturn(0);
2299b08ad5deSksagiyam }
2300b08ad5deSksagiyam 
2301f84dd6b4Sksagiyam /*@
2302a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2303f84dd6b4Sksagiyam 
2304a1cb98faSBarry Smith   Collective on dm
2305f84dd6b4Sksagiyam 
2306f84dd6b4Sksagiyam   Input Parameters:
2307a1cb98faSBarry Smith + dm          - The `DM` that represents the topology
2308a1cb98faSBarry Smith . viewer      - The `PetscViewer` that represents the on-disk section (sectionA)
2309a1cb98faSBarry Smith . sectiondm   - The `DM` into which the on-disk section (sectionA) is migrated
2310a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2311f84dd6b4Sksagiyam 
2312f84dd6b4Sksagiyam   Output Parameters
2313f84dd6b4Sksagiyam + globalDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a global Vec associated with the sectiondm's global section (NULL if not needed)
2314f84dd6b4Sksagiyam - localDofSF  - The SF that migrates any on-disk Vec data associated with sectionA into a local Vec associated with the sectiondm's local section (NULL if not needed)
2315f84dd6b4Sksagiyam 
2316f84dd6b4Sksagiyam   Level: advanced
2317f84dd6b4Sksagiyam 
2318f84dd6b4Sksagiyam   Notes:
2319a1cb98faSBarry 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.
2320f84dd6b4Sksagiyam 
2321a1cb98faSBarry 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.
2322f84dd6b4Sksagiyam 
2323a1cb98faSBarry 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.
2324f84dd6b4Sksagiyam 
2325f84dd6b4Sksagiyam   Example using 2 processes:
2326a1cb98faSBarry Smith .vb
2327a1cb98faSBarry Smith   NX (number of points on dm): 4
2328a1cb98faSBarry Smith   sectionA                   : the on-disk section
2329a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2330a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2331a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2332a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2333f84dd6b4Sksagiyam 
2334a1cb98faSBarry Smith                                      rank 0    rank 1
2335a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2336a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2337a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2338a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2339a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2340a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2341a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2342a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2343a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2344a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2345a1cb98faSBarry Smith .ve
2346a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2347a1cb98faSBarry Smith 
2348a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2349f84dd6b4Sksagiyam @*/
2350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2351d71ae5a4SJacob Faibussowitsch {
2352f84dd6b4Sksagiyam   PetscBool ishdf5;
2353f84dd6b4Sksagiyam 
2354f84dd6b4Sksagiyam   PetscFunctionBegin;
2355f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2356f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2357f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2358f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2359f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2360f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
23619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2363f84dd6b4Sksagiyam   if (ishdf5) {
2364f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
23659566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2366f84dd6b4Sksagiyam #else
2367f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2368f84dd6b4Sksagiyam #endif
2369f84dd6b4Sksagiyam   }
23709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2371f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2372f84dd6b4Sksagiyam }
2373f84dd6b4Sksagiyam 
23748be3dfe1Sksagiyam /*@
23758be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23768be3dfe1Sksagiyam 
2377a1cb98faSBarry Smith   Collective on dm
23788be3dfe1Sksagiyam 
23798be3dfe1Sksagiyam   Input Parameters:
2380a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2381a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2382a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
2383a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
23848be3dfe1Sksagiyam - vec       - The global vector to set values of
23858be3dfe1Sksagiyam 
23868be3dfe1Sksagiyam   Level: advanced
23878be3dfe1Sksagiyam 
23888be3dfe1Sksagiyam   Notes:
2389a1cb98faSBarry 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.
23908be3dfe1Sksagiyam 
2391a1cb98faSBarry Smith   Typical calling sequence:
2392a1cb98faSBarry Smith .vb
2393a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2394a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2395a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2396a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2397a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2398a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2399a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2400a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2401a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2402a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2403a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2404a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2405a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2406a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2407a1cb98faSBarry Smith        DMDestroy(&dm);
2408a1cb98faSBarry Smith .ve
24098be3dfe1Sksagiyam 
2410a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2411a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
24128be3dfe1Sksagiyam @*/
2413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2414d71ae5a4SJacob Faibussowitsch {
24158be3dfe1Sksagiyam   PetscBool ishdf5;
24168be3dfe1Sksagiyam 
24178be3dfe1Sksagiyam   PetscFunctionBegin;
24188be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24198be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24208be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24218be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24228be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24238be3dfe1Sksagiyam   /* Check consistency */
24248be3dfe1Sksagiyam   {
24258be3dfe1Sksagiyam     PetscSection section;
24268be3dfe1Sksagiyam     PetscBool    includesConstraints;
24278be3dfe1Sksagiyam     PetscInt     m, m1;
24288be3dfe1Sksagiyam 
24299566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24309566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
24319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24329566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24339566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
243463a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
24358be3dfe1Sksagiyam   }
24369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
24388be3dfe1Sksagiyam   if (ishdf5) {
24398be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24409566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24418be3dfe1Sksagiyam #else
24428be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24438be3dfe1Sksagiyam #endif
24448be3dfe1Sksagiyam   }
24459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
24468be3dfe1Sksagiyam   PetscFunctionReturn(0);
24478be3dfe1Sksagiyam }
24488be3dfe1Sksagiyam 
24498be3dfe1Sksagiyam /*@
24508be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
24518be3dfe1Sksagiyam 
2452a1cb98faSBarry Smith   Collective on dm
24538be3dfe1Sksagiyam 
24548be3dfe1Sksagiyam   Input Parameters:
2455a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2456a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2457a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined
2458a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
24598be3dfe1Sksagiyam - vec       - The local vector to set values of
24608be3dfe1Sksagiyam 
24618be3dfe1Sksagiyam   Level: advanced
24628be3dfe1Sksagiyam 
24638be3dfe1Sksagiyam   Notes:
2464a1cb98faSBarry 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.
24658be3dfe1Sksagiyam 
2466a1cb98faSBarry Smith   Typical calling sequence:
2467a1cb98faSBarry Smith .vb
2468a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2469a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2470a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2471a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2472a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2473a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2474a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2475a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2476a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2477a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2478a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2479a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2480a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2481a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2482a1cb98faSBarry Smith        DMDestroy(&dm);
2483a1cb98faSBarry Smith .ve
24848be3dfe1Sksagiyam 
2485a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2486a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
24878be3dfe1Sksagiyam @*/
2488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2489d71ae5a4SJacob Faibussowitsch {
24908be3dfe1Sksagiyam   PetscBool ishdf5;
24918be3dfe1Sksagiyam 
24928be3dfe1Sksagiyam   PetscFunctionBegin;
24938be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24948be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24958be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24968be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24978be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24988be3dfe1Sksagiyam   /* Check consistency */
24998be3dfe1Sksagiyam   {
25008be3dfe1Sksagiyam     PetscSection section;
25018be3dfe1Sksagiyam     PetscBool    includesConstraints;
25028be3dfe1Sksagiyam     PetscInt     m, m1;
25038be3dfe1Sksagiyam 
25049566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25059566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
25069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25079566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25089566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
250963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
25108be3dfe1Sksagiyam   }
25119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
25138be3dfe1Sksagiyam   if (ishdf5) {
25148be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
25159566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
25168be3dfe1Sksagiyam #else
25178be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
25188be3dfe1Sksagiyam #endif
25198be3dfe1Sksagiyam   }
25209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
25218be3dfe1Sksagiyam   PetscFunctionReturn(0);
25228be3dfe1Sksagiyam }
25238be3dfe1Sksagiyam 
2524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2525d71ae5a4SJacob Faibussowitsch {
2526552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2527552f7358SJed Brown 
2528552f7358SJed Brown   PetscFunctionBegin;
25299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
25309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
25319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
25329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
25332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
25342e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
25352e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
25362e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
25372e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
25386bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
25396bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2540c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2541c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
25425f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
25430d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
25449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
25459566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
25469566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
25479566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
25489566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
25499566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
25509f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
25519566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
25529566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
25539566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
25549566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
25551d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
25569566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
25579566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
25589566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
25599566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
25609566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
25614e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
25626725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
25636725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
25649566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
25659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
25669566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
25679566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
25689566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
25699566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
25709566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
25719566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
25729566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
25739566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
25749566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2575552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
25769566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
2577552f7358SJed Brown   PetscFunctionReturn(0);
2578552f7358SJed Brown }
2579552f7358SJed Brown 
2580d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2581d71ae5a4SJacob Faibussowitsch {
25828d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2583acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
25849fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2585837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2586b412c318SBarry Smith   MatType                mtype;
25871428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2588552f7358SJed Brown 
2589552f7358SJed Brown   PetscFunctionBegin;
25909566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2591b412c318SBarry Smith   mtype = dm->mattype;
25929566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25939566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25959fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
25969566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25979566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25989566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25999566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
26009566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2601acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
26029566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
26039566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
26049566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
26059566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
26069566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
26079566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
26089566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
26099566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2610552f7358SJed Brown   if (!isShell) {
2611837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
26129fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2613fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2614552f7358SJed Brown 
26159566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
26169fca9976SJed Brown 
26179fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
26189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2619e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
26209fca9976SJed Brown       PetscInt bdof, offset;
2621a9d99c84SMatthew G. Knepley 
26229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
26239fca9976SJed Brown       PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
26249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
26259371c9d4SSatish Balay       for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof;
26261d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof + 1) : dof;
26271d17a0a3SMatthew G. Knepley       bdof = cdof && (dof - cdof) ? 1 : dof;
26281d17a0a3SMatthew G. Knepley       if (dof) {
26299371c9d4SSatish Balay         if (bs < 0) {
26309371c9d4SSatish Balay           bs = bdof;
26319371c9d4SSatish Balay         } else if (bs != bdof) {
26329371c9d4SSatish Balay           bs = 1;
26339371c9d4SSatish Balay         }
2634552f7358SJed Brown       }
26352a28c762SMatthew G Knepley     }
26362a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2637e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2638e432b41dSStefano Zampini     bsLocal[1] = bs;
26399566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2640e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2641e432b41dSStefano Zampini     else bs = bsMinMax[0];
26426fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
26439566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
26440682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
26459566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
26469566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
26470682b8bbSJed Brown     } else {
26489566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
26499566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
26509566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2651552f7358SJed Brown     }
26529fca9976SJed Brown     { // Consolidate blocks
26539fca9976SJed Brown       PetscInt nblocks = 0;
26549fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
26559fca9976SJed Brown         if (pblocks[i] == 0) continue;
26569fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2657ad540459SPierre 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]);
26589fca9976SJed Brown       }
26599fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
26609fca9976SJed Brown     }
26619fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2662aa0f6e3cSJed Brown   }
26639566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
2664552f7358SJed Brown   PetscFunctionReturn(0);
2665552f7358SJed Brown }
2666552f7358SJed Brown 
26677cd05799SMatthew G. Knepley /*@
2668a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2669be36d101SStefano Zampini 
2670a1cb98faSBarry Smith   Not Collective
2671be36d101SStefano Zampini 
2672be36d101SStefano Zampini   Input Parameter:
2673a1cb98faSBarry Smith . mesh - The `DMPLEX`
2674be36d101SStefano Zampini 
2675be36d101SStefano Zampini   Output Parameters:
2676be36d101SStefano Zampini . subsection - The subdomain section
2677be36d101SStefano Zampini 
2678be36d101SStefano Zampini   Level: developer
2679be36d101SStefano Zampini 
2680a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `PetscSection`
26817cd05799SMatthew G. Knepley @*/
2682d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2683d71ae5a4SJacob Faibussowitsch {
2684be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2685be36d101SStefano Zampini 
2686be36d101SStefano Zampini   PetscFunctionBegin;
2687be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2688be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2689be36d101SStefano Zampini     PetscSection section;
2690be36d101SStefano Zampini     PetscSF      sf;
2691be36d101SStefano Zampini 
26929566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
26939566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
26949566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
26959566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2696be36d101SStefano Zampini   }
2697be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2698be36d101SStefano Zampini   PetscFunctionReturn(0);
2699be36d101SStefano Zampini }
2700be36d101SStefano Zampini 
2701552f7358SJed Brown /*@
2702552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2703552f7358SJed Brown 
2704a1cb98faSBarry Smith   Not Collective
2705552f7358SJed Brown 
2706552f7358SJed Brown   Input Parameter:
2707a1cb98faSBarry Smith . mesh - The `DMPLEX`
2708552f7358SJed Brown 
2709552f7358SJed Brown   Output Parameters:
2710552f7358SJed Brown + pStart - The first mesh point
2711552f7358SJed Brown - pEnd   - The upper bound for mesh points
2712552f7358SJed Brown 
2713552f7358SJed Brown   Level: beginner
2714552f7358SJed Brown 
2715a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2716552f7358SJed Brown @*/
2717d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2718d71ae5a4SJacob Faibussowitsch {
2719552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2720552f7358SJed Brown 
2721552f7358SJed Brown   PetscFunctionBegin;
2722552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27239f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
27249f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
2725552f7358SJed Brown   PetscFunctionReturn(0);
2726552f7358SJed Brown }
2727552f7358SJed Brown 
2728552f7358SJed Brown /*@
2729552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2730552f7358SJed Brown 
2731a1cb98faSBarry Smith   Not Collective
2732552f7358SJed Brown 
2733552f7358SJed Brown   Input Parameters:
2734a1cb98faSBarry Smith + mesh - The `DMPLEX`
2735552f7358SJed Brown . pStart - The first mesh point
2736552f7358SJed Brown - pEnd   - The upper bound for mesh points
2737552f7358SJed Brown 
2738552f7358SJed Brown   Level: beginner
2739552f7358SJed Brown 
2740a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2741552f7358SJed Brown @*/
2742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2743d71ae5a4SJacob Faibussowitsch {
2744552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2745552f7358SJed Brown 
2746552f7358SJed Brown   PetscFunctionBegin;
2747552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
27499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2750552f7358SJed Brown   PetscFunctionReturn(0);
2751552f7358SJed Brown }
2752552f7358SJed Brown 
2753552f7358SJed Brown /*@
2754eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2755552f7358SJed Brown 
2756a1cb98faSBarry Smith   Not Collective
2757552f7358SJed Brown 
2758552f7358SJed Brown   Input Parameters:
2759a1cb98faSBarry Smith + mesh - The `DMPLEX`
2760a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
2761552f7358SJed Brown 
2762552f7358SJed Brown   Output Parameter:
2763552f7358SJed Brown . size - The cone size for point p
2764552f7358SJed Brown 
2765552f7358SJed Brown   Level: beginner
2766552f7358SJed Brown 
2767a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2768552f7358SJed Brown @*/
2769d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2770d71ae5a4SJacob Faibussowitsch {
2771552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2772552f7358SJed Brown 
2773552f7358SJed Brown   PetscFunctionBegin;
2774552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2775dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
27769f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
27779f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
2778552f7358SJed Brown   PetscFunctionReturn(0);
2779552f7358SJed Brown }
2780552f7358SJed Brown 
2781552f7358SJed Brown /*@
2782eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2783552f7358SJed Brown 
2784a1cb98faSBarry Smith   Not Collective
2785552f7358SJed Brown 
2786552f7358SJed Brown   Input Parameters:
2787a1cb98faSBarry Smith + mesh - The `DMPLEX`
2788a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
2789552f7358SJed Brown - size - The cone size for point p
2790552f7358SJed Brown 
2791552f7358SJed Brown   Level: beginner
2792552f7358SJed Brown 
2793a1cb98faSBarry Smith   Note:
2794a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
2795a1cb98faSBarry Smith 
2796a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2797552f7358SJed Brown @*/
2798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2799d71ae5a4SJacob Faibussowitsch {
2800552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2801552f7358SJed Brown 
2802552f7358SJed Brown   PetscFunctionBegin;
2803552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28049f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
28059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
2806552f7358SJed Brown   PetscFunctionReturn(0);
2807552f7358SJed Brown }
2808552f7358SJed Brown 
2809552f7358SJed Brown /*@C
2810eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2811552f7358SJed Brown 
2812a1cb98faSBarry Smith   Not Collective
2813552f7358SJed Brown 
2814552f7358SJed Brown   Input Parameters:
2815a1cb98faSBarry Smith + dm - The `DMPLEX`
2816a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
2817552f7358SJed Brown 
2818552f7358SJed Brown   Output Parameter:
2819552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2820552f7358SJed Brown 
2821552f7358SJed Brown   Level: beginner
2822552f7358SJed Brown 
2823a1cb98faSBarry Smith   Fortran Note:
2824a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
2825a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
28263813dfbdSMatthew G Knepley 
2827a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
2828552f7358SJed Brown @*/
2829d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2830d71ae5a4SJacob Faibussowitsch {
2831552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2832552f7358SJed Brown   PetscInt off;
2833552f7358SJed Brown 
2834552f7358SJed Brown   PetscFunctionBegin;
2835552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2836552f7358SJed Brown   PetscValidPointer(cone, 3);
28379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2838552f7358SJed Brown   *cone = &mesh->cones[off];
2839552f7358SJed Brown   PetscFunctionReturn(0);
2840552f7358SJed Brown }
2841552f7358SJed Brown 
28420ce7577fSVaclav Hapla /*@C
28430ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
28440ce7577fSVaclav Hapla 
2845a1cb98faSBarry Smith   Not Collective
28460ce7577fSVaclav Hapla 
28470ce7577fSVaclav Hapla   Input Parameters:
2848a1cb98faSBarry Smith + dm - The `DMPLEX`
2849a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
28500ce7577fSVaclav Hapla 
2851d8d19677SJose E. Roman   Output Parameters:
2852a1cb98faSBarry Smith + pConesSection - `PetscSection` describing the layout of pCones
28530ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
28540ce7577fSVaclav Hapla 
28550ce7577fSVaclav Hapla   Level: intermediate
28560ce7577fSVaclav Hapla 
2857a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
28580ce7577fSVaclav Hapla @*/
2859d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
2860d71ae5a4SJacob Faibussowitsch {
28610ce7577fSVaclav Hapla   PetscSection cs, newcs;
28620ce7577fSVaclav Hapla   PetscInt    *cones;
28630ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
28640ce7577fSVaclav Hapla   PetscInt     n;
28650ce7577fSVaclav Hapla 
28660ce7577fSVaclav Hapla   PetscFunctionBegin;
28679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28699566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
28700ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28710ce7577fSVaclav Hapla   if (pCones) {
28729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28739566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28740ce7577fSVaclav Hapla   }
28750ce7577fSVaclav Hapla   PetscFunctionReturn(0);
28760ce7577fSVaclav Hapla }
28770ce7577fSVaclav Hapla 
2878af9eab45SVaclav Hapla /*@
2879af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2880d4636a37SVaclav Hapla 
2881a1cb98faSBarry Smith   Not Collective
2882d4636a37SVaclav Hapla 
2883d4636a37SVaclav Hapla   Input Parameters:
2884a1cb98faSBarry Smith + dm - The `DMPLEX`
2885a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2886d4636a37SVaclav Hapla 
2887d4636a37SVaclav Hapla   Output Parameter:
2888af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2889d4636a37SVaclav Hapla 
2890d4636a37SVaclav Hapla   Level: advanced
2891d4636a37SVaclav Hapla 
2892af9eab45SVaclav Hapla   Notes:
2893a1cb98faSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth IS (i.e. vertices only) and no sections.
2894af9eab45SVaclav Hapla 
2895a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
2896a1cb98faSBarry Smith 
2897a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
2898a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
2899d4636a37SVaclav Hapla @*/
2900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2901d71ae5a4SJacob Faibussowitsch {
2902af9eab45SVaclav Hapla   IS      *expandedPointsAll;
2903af9eab45SVaclav Hapla   PetscInt depth;
2904d4636a37SVaclav Hapla 
2905d4636a37SVaclav Hapla   PetscFunctionBegin;
2906af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2907af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2908af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
29099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2910af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
29119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
29129566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2913af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2914af9eab45SVaclav Hapla }
2915af9eab45SVaclav Hapla 
2916af9eab45SVaclav Hapla /*@
2917af9eab45SVaclav 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).
2918af9eab45SVaclav Hapla 
2919a1cb98faSBarry Smith   Not Collective
2920af9eab45SVaclav Hapla 
2921af9eab45SVaclav Hapla   Input Parameters:
2922a1cb98faSBarry Smith + dm - The `DMPLEX`
2923a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2924af9eab45SVaclav Hapla 
2925d8d19677SJose E. Roman   Output Parameters:
2926a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
2927af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2928af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2929af9eab45SVaclav Hapla 
2930af9eab45SVaclav Hapla   Level: advanced
2931af9eab45SVaclav Hapla 
2932af9eab45SVaclav Hapla   Notes:
2933a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
2934af9eab45SVaclav Hapla 
2935af9eab45SVaclav Hapla   Array expandedPoints has size equal to depth. Each expandedPoints[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points.
2936af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2937af9eab45SVaclav Hapla 
2938a1cb98faSBarry 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:
2939af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2940af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2941af9eab45SVaclav Hapla 
2942a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
2943a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
2944af9eab45SVaclav Hapla @*/
2945d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2946d71ae5a4SJacob Faibussowitsch {
2947af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
2948af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
2949af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
2950af9eab45SVaclav Hapla   IS             *expandedPoints_;
2951af9eab45SVaclav Hapla   PetscSection   *sections_;
2952af9eab45SVaclav Hapla 
2953af9eab45SVaclav Hapla   PetscFunctionBegin;
2954af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2955af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2956af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2957af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2958af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
29599566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29609566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29629566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29639566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2964af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
2965af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
29669566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29679566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2968af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
2970af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29719566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29729566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2973af9eab45SVaclav Hapla       } else {
29749566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2975af9eab45SVaclav Hapla       }
2976af9eab45SVaclav Hapla     }
29779566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2980af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29829566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2983af9eab45SVaclav Hapla       if (cn > 1) {
29849566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
29859566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
2986af9eab45SVaclav Hapla       } else {
2987af9eab45SVaclav Hapla         newarr[co] = arr[i];
2988af9eab45SVaclav Hapla       }
2989af9eab45SVaclav Hapla     }
29909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2991af9eab45SVaclav Hapla     arr = newarr;
2992af9eab45SVaclav Hapla     n   = newn;
2993af9eab45SVaclav Hapla   }
29949566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
2995af9eab45SVaclav Hapla   *depth = depth_;
2996af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2997af9eab45SVaclav Hapla   else {
29989566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
29999566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3000af9eab45SVaclav Hapla   }
3001af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3002af9eab45SVaclav Hapla   else {
30039566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
30049566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3005af9eab45SVaclav Hapla   }
3006af9eab45SVaclav Hapla   PetscFunctionReturn(0);
3007af9eab45SVaclav Hapla }
3008af9eab45SVaclav Hapla 
3009af9eab45SVaclav Hapla /*@
3010a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3011af9eab45SVaclav Hapla 
3012a1cb98faSBarry Smith   Not Collective
3013af9eab45SVaclav Hapla 
3014af9eab45SVaclav Hapla   Input Parameters:
3015a1cb98faSBarry Smith + dm - The `DMPLEX`
3016a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3017af9eab45SVaclav Hapla 
3018d8d19677SJose E. Roman   Output Parameters:
3019a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3020af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3021af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
3022af9eab45SVaclav Hapla 
3023af9eab45SVaclav Hapla   Level: advanced
3024af9eab45SVaclav Hapla 
3025a1cb98faSBarry Smith   Note:
3026a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3027af9eab45SVaclav Hapla 
3028a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3029a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3030af9eab45SVaclav Hapla @*/
3031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3032d71ae5a4SJacob Faibussowitsch {
3033af9eab45SVaclav Hapla   PetscInt d, depth_;
3034af9eab45SVaclav Hapla 
3035af9eab45SVaclav Hapla   PetscFunctionBegin;
30369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
30371dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3038af9eab45SVaclav Hapla   if (depth) *depth = 0;
3039af9eab45SVaclav Hapla   if (expandedPoints) {
30409566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
30419566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3042af9eab45SVaclav Hapla   }
3043af9eab45SVaclav Hapla   if (sections) {
30449566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
30459566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3046af9eab45SVaclav Hapla   }
3047d4636a37SVaclav Hapla   PetscFunctionReturn(0);
3048d4636a37SVaclav Hapla }
3049d4636a37SVaclav Hapla 
3050552f7358SJed Brown /*@
305192371b87SBarry 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
3052552f7358SJed Brown 
3053a1cb98faSBarry Smith   Not Collective
3054552f7358SJed Brown 
3055552f7358SJed Brown   Input Parameters:
3056a1cb98faSBarry Smith + mesh - The `DMPLEX`
3057a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
3058552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
3059552f7358SJed Brown 
3060552f7358SJed Brown   Level: beginner
3061552f7358SJed Brown 
3062a1cb98faSBarry Smith   Note:
3063a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3064a1cb98faSBarry Smith 
3065a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3066552f7358SJed Brown @*/
3067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3068d71ae5a4SJacob Faibussowitsch {
3069552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3070552f7358SJed Brown   PetscInt pStart, pEnd;
3071552f7358SJed Brown   PetscInt dof, off, c;
3072552f7358SJed Brown 
3073552f7358SJed Brown   PetscFunctionBegin;
3074552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3077dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
307963a3b9bcSJacob 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);
3080552f7358SJed Brown   for (c = 0; c < dof; ++c) {
308163a3b9bcSJacob 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);
3082552f7358SJed Brown     mesh->cones[off + c] = cone[c];
3083552f7358SJed Brown   }
3084552f7358SJed Brown   PetscFunctionReturn(0);
3085552f7358SJed Brown }
3086552f7358SJed Brown 
3087552f7358SJed Brown /*@C
3088eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3089552f7358SJed Brown 
3090a1cb98faSBarry Smith   Not Collective
3091552f7358SJed Brown 
3092552f7358SJed Brown   Input Parameters:
3093a1cb98faSBarry Smith + mesh - The `DMPLEX`
3094a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3095552f7358SJed Brown 
3096552f7358SJed Brown   Output Parameter:
3097552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3098b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3099552f7358SJed Brown 
3100552f7358SJed Brown   Level: beginner
3101552f7358SJed Brown 
3102a1cb98faSBarry Smith   Note:
3103b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3104b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3105a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3106b5a892a1SMatthew G. Knepley   with the identity.
3107b5a892a1SMatthew G. Knepley 
3108a1cb98faSBarry Smith   Fortran Note:
3109a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3110a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
31113813dfbdSMatthew G Knepley 
3112a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3113552f7358SJed Brown @*/
3114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3115d71ae5a4SJacob Faibussowitsch {
3116552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3117552f7358SJed Brown   PetscInt off;
3118552f7358SJed Brown 
3119552f7358SJed Brown   PetscFunctionBegin;
3120552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
312176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3122552f7358SJed Brown     PetscInt dof;
31239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3124552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3125552f7358SJed Brown   }
31269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
31270d644c17SKarl Rupp 
3128552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3129552f7358SJed Brown   PetscFunctionReturn(0);
3130552f7358SJed Brown }
3131552f7358SJed Brown 
3132552f7358SJed Brown /*@
3133eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3134552f7358SJed Brown 
3135a1cb98faSBarry Smith   Not Collective
3136552f7358SJed Brown 
3137552f7358SJed Brown   Input Parameters:
3138a1cb98faSBarry Smith + mesh - The `DMPLEX`
3139a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
3140b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3141b5a892a1SMatthew G. Knepley 
3142552f7358SJed Brown   Level: beginner
3143552f7358SJed Brown 
3144a1cb98faSBarry Smith   Notes:
3145a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3146a1cb98faSBarry Smith 
3147a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3148a1cb98faSBarry Smith 
3149a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3150552f7358SJed Brown @*/
3151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3152d71ae5a4SJacob Faibussowitsch {
3153552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3154552f7358SJed Brown   PetscInt pStart, pEnd;
3155552f7358SJed Brown   PetscInt dof, off, c;
3156552f7358SJed Brown 
3157552f7358SJed Brown   PetscFunctionBegin;
3158552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3161dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
31629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
316363a3b9bcSJacob 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);
3164552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3165552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3166552f7358SJed Brown 
31679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
31681dca8a05SBarry 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);
3169552f7358SJed Brown     mesh->coneOrientations[off + c] = o;
3170552f7358SJed Brown   }
3171552f7358SJed Brown   PetscFunctionReturn(0);
3172552f7358SJed Brown }
3173552f7358SJed Brown 
31747cd05799SMatthew G. Knepley /*@
3175eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31767cd05799SMatthew G. Knepley 
3177a1cb98faSBarry Smith   Not Collective
31787cd05799SMatthew G. Knepley 
31797cd05799SMatthew G. Knepley   Input Parameters:
3180a1cb98faSBarry Smith + mesh - The `DMPLEX`
3181a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
31827cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31837cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31847cd05799SMatthew G. Knepley 
31857cd05799SMatthew G. Knepley   Level: beginner
31867cd05799SMatthew G. Knepley 
3187a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31887cd05799SMatthew G. Knepley @*/
3189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3190d71ae5a4SJacob Faibussowitsch {
3191552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3192552f7358SJed Brown   PetscInt pStart, pEnd;
3193552f7358SJed Brown   PetscInt dof, off;
3194552f7358SJed Brown 
3195552f7358SJed Brown   PetscFunctionBegin;
3196552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
319863a3b9bcSJacob 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);
319963a3b9bcSJacob 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);
32009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
320263a3b9bcSJacob 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);
3203552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
3204552f7358SJed Brown   PetscFunctionReturn(0);
3205552f7358SJed Brown }
3206552f7358SJed Brown 
32077cd05799SMatthew G. Knepley /*@
3208eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
32097cd05799SMatthew G. Knepley 
3210a1cb98faSBarry Smith   Not Collective
32117cd05799SMatthew G. Knepley 
32127cd05799SMatthew G. Knepley   Input Parameters:
3213a1cb98faSBarry Smith + mesh - The `DMPLEX`
3214a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
32157cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
32167cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
32177cd05799SMatthew G. Knepley 
32187cd05799SMatthew G. Knepley   Level: beginner
32197cd05799SMatthew G. Knepley 
3220a1cb98faSBarry Smith   Note:
3221a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3222b5a892a1SMatthew G. Knepley 
3223a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32247cd05799SMatthew G. Knepley @*/
3225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3226d71ae5a4SJacob Faibussowitsch {
322777c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
322877c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
322977c88f5bSMatthew G Knepley   PetscInt dof, off;
323077c88f5bSMatthew G Knepley 
323177c88f5bSMatthew G Knepley   PetscFunctionBegin;
323277c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
323463a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
32359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
323763a3b9bcSJacob Faibussowitsch   PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
323877c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
323977c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
324077c88f5bSMatthew G Knepley }
324177c88f5bSMatthew G Knepley 
32429f4ada15SMatthew G. Knepley /*@C
32439f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
32449f4ada15SMatthew G. Knepley 
32459f4ada15SMatthew G. Knepley   Not collective
32469f4ada15SMatthew G. Knepley 
32479f4ada15SMatthew G. Knepley   Input Parameters:
32489f4ada15SMatthew G. Knepley + dm - The DMPlex
32499f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
32509f4ada15SMatthew G. Knepley 
32519f4ada15SMatthew G. Knepley   Output Parameters:
32529f4ada15SMatthew G. Knepley + cone - An array of points which are on the in-edges for point p
32539f4ada15SMatthew G. Knepley - ornt - An array of orientations which are on the in-edges for point p. An orientation is an
32549f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
32559f4ada15SMatthew G. Knepley 
32569f4ada15SMatthew G. Knepley   Level: beginner
32579f4ada15SMatthew G. Knepley 
32589f4ada15SMatthew G. Knepley   Notes:
32599f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
32609f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
32619f4ada15SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
32629f4ada15SMatthew G. Knepley   with the identity.
32639f4ada15SMatthew G. Knepley 
32649f4ada15SMatthew G. Knepley   Fortran Notes:
32659f4ada15SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32669f4ada15SMatthew G. Knepley   include petsc.h90 in your code.
32679f4ada15SMatthew G. Knepley   You must also call DMPlexRestoreCone() after you finish using the returned array.
32689f4ada15SMatthew G. Knepley   DMPlexRestoreCone() is not needed/available in C.
32699f4ada15SMatthew G. Knepley 
32709f4ada15SMatthew G. Knepley .seealso: `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
32719f4ada15SMatthew G. Knepley @*/
32729f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
32739f4ada15SMatthew G. Knepley {
32749f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
32759f4ada15SMatthew G. Knepley 
32769f4ada15SMatthew G. Knepley   PetscFunctionBegin;
32779f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32789f4ada15SMatthew G. Knepley   if (mesh->tr) {
32799f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
32809f4ada15SMatthew G. Knepley   } else {
32819f4ada15SMatthew G. Knepley     PetscInt off;
32829f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
32839f4ada15SMatthew G. Knepley       PetscInt dof;
32849f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32859f4ada15SMatthew G. Knepley       if (dof) {
32869f4ada15SMatthew G. Knepley         if (cone) PetscValidPointer(cone, 3);
32879f4ada15SMatthew G. Knepley         if (ornt) PetscValidPointer(ornt, 4);
32889f4ada15SMatthew G. Knepley       }
32899f4ada15SMatthew G. Knepley     }
32909f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
32919f4ada15SMatthew G. Knepley     if (cone) *cone = &mesh->cones[off];
32929f4ada15SMatthew G. Knepley     if (ornt) *ornt = &mesh->coneOrientations[off];
32939f4ada15SMatthew G. Knepley   }
32949f4ada15SMatthew G. Knepley   PetscFunctionReturn(0);
32959f4ada15SMatthew G. Knepley }
32969f4ada15SMatthew G. Knepley 
32979f4ada15SMatthew G. Knepley /*@C
32989f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
32999f4ada15SMatthew G. Knepley 
33009f4ada15SMatthew G. Knepley   Not collective
33019f4ada15SMatthew G. Knepley 
33029f4ada15SMatthew G. Knepley   Input Parameters:
33039f4ada15SMatthew G. Knepley + dm - The DMPlex
33049f4ada15SMatthew G. Knepley . p  - The point, which must lie in the chart set with DMPlexSetChart()
33059f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
33069f4ada15SMatthew G. Knepley - ornt - An array of orientations which are on the in-edges for point p. An orientation is an
33079f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
33089f4ada15SMatthew G. Knepley 
33099f4ada15SMatthew G. Knepley   Level: beginner
33109f4ada15SMatthew G. Knepley 
33119f4ada15SMatthew G. Knepley   Notes:
33129f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
33139f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
33149f4ada15SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
33159f4ada15SMatthew G. Knepley   with the identity.
33169f4ada15SMatthew G. Knepley 
33179f4ada15SMatthew G. Knepley   Fortran Notes:
33189f4ada15SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
33199f4ada15SMatthew G. Knepley   include petsc.h90 in your code.
33209f4ada15SMatthew G. Knepley   You must also call DMPlexRestoreCone() after you finish using the returned array.
33219f4ada15SMatthew G. Knepley   DMPlexRestoreCone() is not needed/available in C.
33229f4ada15SMatthew G. Knepley 
33239f4ada15SMatthew G. Knepley .seealso: `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
33249f4ada15SMatthew G. Knepley @*/
33259f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
33269f4ada15SMatthew G. Knepley {
33279f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
33289f4ada15SMatthew G. Knepley 
33299f4ada15SMatthew G. Knepley   PetscFunctionBegin;
33309f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33319f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
33329f4ada15SMatthew G. Knepley   PetscFunctionReturn(0);
33339f4ada15SMatthew G. Knepley }
33349f4ada15SMatthew G. Knepley 
3335552f7358SJed Brown /*@
3336eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3337552f7358SJed Brown 
3338a1cb98faSBarry Smith   Not Collective
3339552f7358SJed Brown 
3340552f7358SJed Brown   Input Parameters:
3341a1cb98faSBarry Smith + mesh - The `DMPLEX`
3342a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3343552f7358SJed Brown 
3344552f7358SJed Brown   Output Parameter:
3345552f7358SJed Brown . size - The support size for point p
3346552f7358SJed Brown 
3347552f7358SJed Brown   Level: beginner
3348552f7358SJed Brown 
3349a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3350552f7358SJed Brown @*/
3351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3352d71ae5a4SJacob Faibussowitsch {
3353552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3354552f7358SJed Brown 
3355552f7358SJed Brown   PetscFunctionBegin;
3356552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3357dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
33589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
3359552f7358SJed Brown   PetscFunctionReturn(0);
3360552f7358SJed Brown }
3361552f7358SJed Brown 
3362552f7358SJed Brown /*@
3363eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3364552f7358SJed Brown 
3365a1cb98faSBarry Smith   Not Collective
3366552f7358SJed Brown 
3367552f7358SJed Brown   Input Parameters:
3368a1cb98faSBarry Smith + mesh - The `DMPLEX`
3369a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
3370552f7358SJed Brown - size - The support size for point p
3371552f7358SJed Brown 
3372a1cb98faSBarry Smith   Level: beginner
3373552f7358SJed Brown 
3374552f7358SJed Brown   Note:
3375552f7358SJed Brown   This should be called after DMPlexSetChart().
3376552f7358SJed Brown 
3377a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3378552f7358SJed Brown @*/
3379d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3380d71ae5a4SJacob Faibussowitsch {
3381552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3382552f7358SJed Brown 
3383552f7358SJed Brown   PetscFunctionBegin;
3384552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
3386552f7358SJed Brown   PetscFunctionReturn(0);
3387552f7358SJed Brown }
3388552f7358SJed Brown 
3389552f7358SJed Brown /*@C
3390eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3391552f7358SJed Brown 
3392a1cb98faSBarry Smith   Not Collective
3393552f7358SJed Brown 
3394552f7358SJed Brown   Input Parameters:
3395a1cb98faSBarry Smith + mesh - The `DMPLEX`
3396a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()`
3397552f7358SJed Brown 
3398552f7358SJed Brown   Output Parameter:
3399552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3400552f7358SJed Brown 
3401552f7358SJed Brown   Level: beginner
3402552f7358SJed Brown 
3403a1cb98faSBarry Smith   Fortran Note:
3404a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3405a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
34063813dfbdSMatthew G Knepley 
3407a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3408552f7358SJed Brown @*/
3409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3410d71ae5a4SJacob Faibussowitsch {
3411552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3412552f7358SJed Brown   PetscInt off;
3413552f7358SJed Brown 
3414552f7358SJed Brown   PetscFunctionBegin;
3415552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3416552f7358SJed Brown   PetscValidPointer(support, 3);
34179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3418552f7358SJed Brown   *support = &mesh->supports[off];
3419552f7358SJed Brown   PetscFunctionReturn(0);
3420552f7358SJed Brown }
3421552f7358SJed Brown 
3422552f7358SJed Brown /*@
342392371b87SBarry 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
3424552f7358SJed Brown 
3425a1cb98faSBarry Smith   Not Collective
3426552f7358SJed Brown 
3427552f7358SJed Brown   Input Parameters:
3428a1cb98faSBarry Smith + mesh - The `DMPLEX`
3429a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
343092371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3431552f7358SJed Brown 
3432552f7358SJed Brown   Level: beginner
3433552f7358SJed Brown 
3434a1cb98faSBarry Smith   Note:
3435a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3436a1cb98faSBarry Smith 
3437a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3438552f7358SJed Brown @*/
3439d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3440d71ae5a4SJacob Faibussowitsch {
3441552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3442552f7358SJed Brown   PetscInt pStart, pEnd;
3443552f7358SJed Brown   PetscInt dof, off, c;
3444552f7358SJed Brown 
3445552f7358SJed Brown   PetscFunctionBegin;
3446552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
34489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3449dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
34509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
345163a3b9bcSJacob 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);
3452552f7358SJed Brown   for (c = 0; c < dof; ++c) {
345363a3b9bcSJacob 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);
3454552f7358SJed Brown     mesh->supports[off + c] = support[c];
3455552f7358SJed Brown   }
3456552f7358SJed Brown   PetscFunctionReturn(0);
3457552f7358SJed Brown }
3458552f7358SJed Brown 
34597cd05799SMatthew G. Knepley /*@
3460eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
34617cd05799SMatthew G. Knepley 
3462a1cb98faSBarry Smith   Not Collective
34637cd05799SMatthew G. Knepley 
34647cd05799SMatthew G. Knepley   Input Parameters:
3465a1cb98faSBarry Smith + mesh - The `DMPLEX`
3466a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()`
34677cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
34687cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
34697cd05799SMatthew G. Knepley 
34707cd05799SMatthew G. Knepley   Level: beginner
34717cd05799SMatthew G. Knepley 
3472a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34737cd05799SMatthew G. Knepley @*/
3474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3475d71ae5a4SJacob Faibussowitsch {
3476552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3477552f7358SJed Brown   PetscInt pStart, pEnd;
3478552f7358SJed Brown   PetscInt dof, off;
3479552f7358SJed Brown 
3480552f7358SJed Brown   PetscFunctionBegin;
3481552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
34839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
34849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
348563a3b9bcSJacob 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);
348663a3b9bcSJacob 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);
348763a3b9bcSJacob 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);
3488552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
3489552f7358SJed Brown   PetscFunctionReturn(0);
3490552f7358SJed Brown }
3491552f7358SJed Brown 
3492b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3493d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3494d71ae5a4SJacob Faibussowitsch {
3495b5a892a1SMatthew G. Knepley   switch (ct) {
3496b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3497b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3498b5a892a1SMatthew G. Knepley     break;
3499b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3500b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3501b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3502b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3503b5a892a1SMatthew G. Knepley     break;
3504b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3505b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3506b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3507b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3508b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3509b5a892a1SMatthew G. Knepley     break;
3510d71ae5a4SJacob Faibussowitsch   default:
3511d71ae5a4SJacob Faibussowitsch     return o;
3512b5a892a1SMatthew G. Knepley   }
3513b5a892a1SMatthew G. Knepley   return o;
3514b5a892a1SMatthew G. Knepley }
3515b5a892a1SMatthew G. Knepley 
3516b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3517d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3518d71ae5a4SJacob Faibussowitsch {
3519b5a892a1SMatthew G. Knepley   switch (ct) {
3520b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3521b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3522b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3523b5a892a1SMatthew G. Knepley     break;
3524b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3525b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3526b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3527b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3528b5a892a1SMatthew G. Knepley     break;
3529b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3530b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3531b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3532b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3533b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3534b5a892a1SMatthew G. Knepley     break;
3535d71ae5a4SJacob Faibussowitsch   default:
3536d71ae5a4SJacob Faibussowitsch     return o;
3537b5a892a1SMatthew G. Knepley   }
3538b5a892a1SMatthew G. Knepley   return o;
3539b5a892a1SMatthew G. Knepley }
3540b5a892a1SMatthew G. Knepley 
3541b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3542d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3543d71ae5a4SJacob Faibussowitsch {
3544b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3545b5a892a1SMatthew G. Knepley 
3546b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
35479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3548b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3549b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3550b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3551b5a892a1SMatthew G. Knepley 
35529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
35539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
35549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3555b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3556b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3557b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3558b5a892a1SMatthew G. Knepley 
35599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3560b5a892a1SMatthew G. Knepley       switch (ct) {
3561b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
35629566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35639566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3564b5a892a1SMatthew G. Knepley         break;
3565b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
35669566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
35679566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35689566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3569b5a892a1SMatthew G. Knepley         break;
3570b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
35719566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
35729566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35739566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
35749566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3575b5a892a1SMatthew G. Knepley         break;
3576d71ae5a4SJacob Faibussowitsch       default:
3577d71ae5a4SJacob Faibussowitsch         break;
3578b5a892a1SMatthew G. Knepley       }
3579b5a892a1SMatthew G. Knepley     }
3580b5a892a1SMatthew G. Knepley   }
3581b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3582b5a892a1SMatthew G. Knepley }
3583b5a892a1SMatthew G. Knepley 
3584d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3585d71ae5a4SJacob Faibussowitsch {
3586b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3587b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3588b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3589b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3590b5a892a1SMatthew G. Knepley 
3591b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3592b5a892a1SMatthew G. Knepley   if (ornt) {
35939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3594b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3595b5a892a1SMatthew G. Knepley   }
3596b5a892a1SMatthew G. Knepley   if (*points) {
3597b5a892a1SMatthew G. Knepley     closure = *points;
3598b5a892a1SMatthew G. Knepley   } else {
3599b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
36009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
36019566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3602b5a892a1SMatthew G. Knepley   }
3603b5a892a1SMatthew G. Knepley   if (useCone) {
36049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
36059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
36069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3607b5a892a1SMatthew G. Knepley   } else {
36089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
36099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3610b5a892a1SMatthew G. Knepley   }
3611b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3612b5a892a1SMatthew G. Knepley     closure[off++] = p;
3613b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3614b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3615b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3616b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3617b5a892a1SMatthew G. Knepley     }
3618b5a892a1SMatthew G. Knepley   } else {
36195f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3620b5a892a1SMatthew G. Knepley 
3621b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3622b5a892a1SMatthew G. Knepley     closure[off++] = p;
3623b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3624b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3625b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3626b5a892a1SMatthew G. Knepley 
36279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3628b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3629b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3630b5a892a1SMatthew G. Knepley     }
3631b5a892a1SMatthew G. Knepley   }
3632b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3633b5a892a1SMatthew G. Knepley   if (points) *points = closure;
3634b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3635b5a892a1SMatthew G. Knepley }
3636b5a892a1SMatthew G. Knepley 
3637d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3638d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3639d71ae5a4SJacob Faibussowitsch {
3640b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3641b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3642b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3643b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3644b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3645b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3646b5a892a1SMatthew G. Knepley 
3647b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
36489566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
36499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
36509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
36519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
36529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3653b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3654b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3655b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
36569371c9d4SSatish Balay   if (*points) {
36579371c9d4SSatish Balay     pts = *points;
36589371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3659b5a892a1SMatthew G. Knepley   c        = 0;
3660b5a892a1SMatthew G. Knepley   pts[c++] = point;
3661b5a892a1SMatthew G. Knepley   pts[c++] = o;
36629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
36639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
36649371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
36659371c9d4SSatish Balay     pts[c++] = closure[cl];
36669371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
36679371c9d4SSatish Balay   }
36689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
36699371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
36709371c9d4SSatish Balay     pts[c++] = closure[cl];
36719371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
36729371c9d4SSatish Balay   }
36739566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3674b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
36759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3676b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3677b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3678b5a892a1SMatthew G. Knepley   }
3679b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3680b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3681b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3682b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3683b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3684b5a892a1SMatthew G. Knepley 
36859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3686b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
36879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
36889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
36899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3690b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3691b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3692b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3693b5a892a1SMatthew G. Knepley 
36949371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
36959371c9d4SSatish Balay           if (pts[i] == cp) break;
3696b5a892a1SMatthew G. Knepley         if (i == c) {
36979566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3698b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3699b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3700b5a892a1SMatthew G. Knepley         }
3701b5a892a1SMatthew G. Knepley       }
3702b5a892a1SMatthew G. Knepley     }
3703b5a892a1SMatthew G. Knepley   }
3704b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3705b5a892a1SMatthew G. Knepley   *points    = pts;
3706b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3707b5a892a1SMatthew G. Knepley }
3708b5a892a1SMatthew G. Knepley 
3709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3710d71ae5a4SJacob Faibussowitsch {
3711b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3712b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3713b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3714b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3715b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3716b5a892a1SMatthew G. Knepley 
3717b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
37189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3719b5a892a1SMatthew G. Knepley   if (depth == 1) {
37209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3721b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3722b5a892a1SMatthew G. Knepley   }
37239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3724b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3725b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
37269566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3727b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3728b5a892a1SMatthew G. Knepley   }
37299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3730b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3731b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3732b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
37339566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
37349371c9d4SSatish Balay   if (*points) {
37359371c9d4SSatish Balay     closure = *points;
37369371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3737b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3738b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3739b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3740b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3741b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3742b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3743b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3744b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3745b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3746b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
3747b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3748b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3749b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3750b5a892a1SMatthew G. Knepley 
3751b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3752b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2;
375363a3b9bcSJacob 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);
3754b5a892a1SMatthew G. Knepley     }
3755b5a892a1SMatthew G. Knepley     if (useCone) {
37569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
37579566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
37589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3759b5a892a1SMatthew G. Knepley     } else {
37609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
37619566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3762b5a892a1SMatthew G. Knepley       tmpO = NULL;
3763b5a892a1SMatthew G. Knepley     }
3764b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3765b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
3766b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
3767b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
37689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3769b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3770b5a892a1SMatthew G. Knepley       PetscInt       c;
3771b5a892a1SMatthew G. Knepley 
3772b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3773b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3774b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3775b5a892a1SMatthew G. Knepley       }
3776b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3777b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3778b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3779b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3780b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3781b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3782b5a892a1SMatthew G. Knepley       }
3783b5a892a1SMatthew G. Knepley     }
3784b5a892a1SMatthew G. Knepley   }
37859566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
3786b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
3787b5a892a1SMatthew G. Knepley   if (points) *points = closure;
3788b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3789b5a892a1SMatthew G. Knepley }
3790b5a892a1SMatthew G. Knepley 
3791552f7358SJed Brown /*@C
3792eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3793552f7358SJed Brown 
3794a1cb98faSBarry Smith   Not Collective
3795552f7358SJed Brown 
3796552f7358SJed Brown   Input Parameters:
3797a1cb98faSBarry Smith + dm      - The `DMPLEX`
3798b5a892a1SMatthew G. Knepley . p       - The mesh point
3799a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
3800552f7358SJed Brown 
38016b867d5aSJose E. Roman   Input/Output Parameter:
38026b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
38036b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
38046b867d5aSJose E. Roman 
38056b867d5aSJose E. Roman   Output Parameter:
38066b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3807552f7358SJed Brown 
3808a1cb98faSBarry Smith   Level: beginner
3809a1cb98faSBarry Smith 
3810552f7358SJed Brown   Note:
38110298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3812552f7358SJed Brown 
38139f22da38SBarry Smith   Fortran Note:
3814a1cb98faSBarry Smith   The numPoints argument is not present in the Fortran binding since it is internal to the array.
38153813dfbdSMatthew G Knepley 
3816a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3817552f7358SJed Brown @*/
3818d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3819d71ae5a4SJacob Faibussowitsch {
3820b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3821552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3822b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3823b5a892a1SMatthew G. Knepley   if (points) PetscValidPointer(points, 5);
38249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
38259bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
38269bf0dad6SMatthew G. Knepley }
38279bf0dad6SMatthew G. Knepley 
3828552f7358SJed Brown /*@C
3829eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3830552f7358SJed Brown 
3831a1cb98faSBarry Smith   Not Collective
3832552f7358SJed Brown 
3833552f7358SJed Brown   Input Parameters:
3834a1cb98faSBarry Smith + dm        - The `DMPLEX`
3835b5a892a1SMatthew G. Knepley . p         - The mesh point
3836a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
3837b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3838b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3839552f7358SJed Brown 
3840a1cb98faSBarry Smith   Level: beginner
3841a1cb98faSBarry Smith 
3842552f7358SJed Brown   Note:
38430298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3844552f7358SJed Brown 
3845a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3846552f7358SJed Brown @*/
3847d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3848d71ae5a4SJacob Faibussowitsch {
3849b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3850552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38514ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
38529566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3853552f7358SJed Brown   PetscFunctionReturn(0);
3854552f7358SJed Brown }
3855552f7358SJed Brown 
3856552f7358SJed Brown /*@
3857eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3858552f7358SJed Brown 
3859a1cb98faSBarry Smith   Not Collective
3860552f7358SJed Brown 
3861552f7358SJed Brown   Input Parameter:
3862a1cb98faSBarry Smith . mesh - The `DMPLEX`
3863552f7358SJed Brown 
3864552f7358SJed Brown   Output Parameters:
3865552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3866552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3867552f7358SJed Brown 
3868552f7358SJed Brown   Level: beginner
3869552f7358SJed Brown 
3870a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3871552f7358SJed Brown @*/
3872d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3873d71ae5a4SJacob Faibussowitsch {
3874552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3875552f7358SJed Brown 
3876552f7358SJed Brown   PetscFunctionBegin;
3877552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38781baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
38791baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
3880552f7358SJed Brown   PetscFunctionReturn(0);
3881552f7358SJed Brown }
3882552f7358SJed Brown 
3883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
3884d71ae5a4SJacob Faibussowitsch {
3885552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
38866302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
3887552f7358SJed Brown 
3888552f7358SJed Brown   PetscFunctionBegin;
3889552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
38919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
38929566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
38939566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
38946302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
38956302a7fbSVaclav Hapla   if (maxSupportSize) {
38969566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
38979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
38989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
3899552f7358SJed Brown   }
3900552f7358SJed Brown   PetscFunctionReturn(0);
3901552f7358SJed Brown }
3902552f7358SJed Brown 
3903d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3904d71ae5a4SJacob Faibussowitsch {
3905552f7358SJed Brown   PetscFunctionBegin;
39069566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
39079566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3908ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
3909736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
391095602cf2SAlexis Marboeuf     PetscSF sfNatural;
3911f94b4a02SBlaise Bourdin 
39123dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
39139566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
391495602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
3915c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3916f94b4a02SBlaise Bourdin   }
3917552f7358SJed Brown   PetscFunctionReturn(0);
3918552f7358SJed Brown }
3919552f7358SJed Brown 
3920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
3921d71ae5a4SJacob Faibussowitsch {
39223dcd263cSBlaise Bourdin   PetscInt i = 0;
39232adcc780SMatthew G. Knepley 
39242adcc780SMatthew G. Knepley   PetscFunctionBegin;
39259566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
39269566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3927c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
39283dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
39293dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
393095602cf2SAlexis Marboeuf       PetscSF sfNatural;
39313dcd263cSBlaise Bourdin 
39323dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
39339566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
3934c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
393595602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
3936c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
39373dcd263cSBlaise Bourdin       break;
39383dcd263cSBlaise Bourdin     }
39393dcd263cSBlaise Bourdin   }
39402adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
39412adcc780SMatthew G. Knepley }
39422adcc780SMatthew G. Knepley 
3943552f7358SJed Brown /*@
3944eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3945552f7358SJed Brown 
3946a1cb98faSBarry Smith   Not Collective
3947552f7358SJed Brown 
3948552f7358SJed Brown   Input Parameter:
3949a1cb98faSBarry Smith . mesh - The `DMPLEX`
3950552f7358SJed Brown 
3951552f7358SJed Brown   Level: beginner
3952552f7358SJed Brown 
3953a1cb98faSBarry Smith   Note:
3954a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
3955a1cb98faSBarry Smith 
3956a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3957552f7358SJed Brown @*/
3958d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
3959d71ae5a4SJacob Faibussowitsch {
3960552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
3961552f7358SJed Brown   PetscInt *offsets;
3962552f7358SJed Brown   PetscInt  supportSize;
3963552f7358SJed Brown   PetscInt  pStart, pEnd, p;
3964552f7358SJed Brown 
3965552f7358SJed Brown   PetscFunctionBegin;
3966552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
396728b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
39689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
3969552f7358SJed Brown   /* Calculate support sizes */
39709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3971552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3972552f7358SJed Brown     PetscInt dof, off, c;
3973552f7358SJed Brown 
39749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
39759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
397648a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3977552f7358SJed Brown   }
39789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3979552f7358SJed Brown   /* Calculate supports */
39809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
39819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
39829566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3983552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3984552f7358SJed Brown     PetscInt dof, off, c;
3985552f7358SJed Brown 
39869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
39879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3988552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
3989552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3990552f7358SJed Brown       PetscInt       offS;
3991552f7358SJed Brown 
39929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
39930d644c17SKarl Rupp 
3994552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
3995552f7358SJed Brown       ++offsets[q];
3996552f7358SJed Brown     }
3997552f7358SJed Brown   }
39989566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
39999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
4000552f7358SJed Brown   PetscFunctionReturn(0);
4001552f7358SJed Brown }
4002552f7358SJed Brown 
4003d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4004d71ae5a4SJacob Faibussowitsch {
4005277ea44aSLisandro Dalcin   IS stratumIS;
4006277ea44aSLisandro Dalcin 
4007277ea44aSLisandro Dalcin   PetscFunctionBegin;
4008277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
400976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4010277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4011277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
40129566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4013277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
40149566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
40159371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
40169371c9d4SSatish Balay         overlap = PETSC_TRUE;
40179371c9d4SSatish Balay         break;
40189371c9d4SSatish Balay       }
4019277ea44aSLisandro Dalcin     }
402063a3b9bcSJacob 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);
4021277ea44aSLisandro Dalcin   }
40229566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
40239566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
40249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
4025277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
4026277ea44aSLisandro Dalcin }
4027277ea44aSLisandro Dalcin 
4028552f7358SJed Brown /*@
4029a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
40306dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
4031552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
4032552f7358SJed Brown   the DAG.
4033552f7358SJed Brown 
4034bf4602e4SToby Isaac   Collective on dm
4035552f7358SJed Brown 
4036552f7358SJed Brown   Input Parameter:
4037a1cb98faSBarry Smith . mesh - The `DMPLEX`
4038552f7358SJed Brown 
4039a1cb98faSBarry Smith   Level: beginner
4040552f7358SJed Brown 
4041552f7358SJed Brown   Notes:
4042a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4043b1bb481bSMatthew 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
4044a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4045a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4046a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4047552f7358SJed Brown 
4048b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4049b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4050b1bb481bSMatthew 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
4051b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4052a1cb98faSBarry Smith .vb
4053a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4054a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4055a1cb98faSBarry Smith .ve
4056a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4057a1cb98faSBarry Smith .vb
4058a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4059a1cb98faSBarry Smith    depth 1 = {e0, c0}
4060a1cb98faSBarry Smith .ve
4061b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4062b1bb481bSMatthew Knepley 
4063a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4064552f7358SJed Brown 
4065a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4066552f7358SJed Brown @*/
4067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4068d71ae5a4SJacob Faibussowitsch {
4069df0420ecSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4070aa50250dSMatthew G. Knepley   DMLabel  label;
4071552f7358SJed Brown   PetscInt pStart, pEnd, p;
4072552f7358SJed Brown   PetscInt numRoots = 0, numLeaves = 0;
4073552f7358SJed Brown 
4074552f7358SJed Brown   PetscFunctionBegin;
4075552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4077277ea44aSLisandro Dalcin 
4078277ea44aSLisandro Dalcin   /* Create depth label */
40799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
40809566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
40819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4082277ea44aSLisandro Dalcin 
4083277ea44aSLisandro Dalcin   {
4084552f7358SJed Brown     /* Initialize roots and count leaves */
4085277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4086277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4087552f7358SJed Brown     PetscInt coneSize, supportSize;
4088552f7358SJed Brown 
4089277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
40909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
40919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4092552f7358SJed Brown       if (!coneSize && supportSize) {
4093277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4094277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4095552f7358SJed Brown         ++numRoots;
4096552f7358SJed Brown       } else if (!supportSize && coneSize) {
4097552f7358SJed Brown         ++numLeaves;
4098552f7358SJed Brown       } else if (!supportSize && !coneSize) {
4099552f7358SJed Brown         /* Isolated points */
4100277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4101277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4102552f7358SJed Brown       }
4103552f7358SJed Brown     }
41049566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4105277ea44aSLisandro Dalcin   }
4106277ea44aSLisandro Dalcin 
4107552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
4108277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4109277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4110552f7358SJed Brown     PetscInt coneSize, supportSize;
4111552f7358SJed Brown 
4112277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
41139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4115552f7358SJed Brown       if (!supportSize && coneSize) {
4116277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4117277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4118552f7358SJed Brown       }
4119552f7358SJed Brown     }
41209566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4121552f7358SJed Brown   } else {
4122277ea44aSLisandro Dalcin     PetscInt level = 0;
4123277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
4124552f7358SJed Brown 
41259566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4126277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4127277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4128277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
412974ef644bSMatthew G. Knepley 
4130277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
413174ef644bSMatthew G. Knepley         const PetscInt *support;
413274ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
413374ef644bSMatthew G. Knepley 
41349566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
41359566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
413674ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4137277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4138277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4139552f7358SJed Brown         }
4140552f7358SJed Brown       }
41419566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
41429566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
41439566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
414474ef644bSMatthew G. Knepley     }
414574ef644bSMatthew G. Knepley   }
4146bf4602e4SToby Isaac   { /* just in case there is an empty process */
4147bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4148bf4602e4SToby Isaac 
41499566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
41509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
415148a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4152bf4602e4SToby Isaac   }
41539566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
41549566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
4155552f7358SJed Brown   PetscFunctionReturn(0);
4156552f7358SJed Brown }
4157552f7358SJed Brown 
4158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4159d71ae5a4SJacob Faibussowitsch {
4160412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4161412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4162ba2698f1SMatthew G. Knepley 
4163412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
41649566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
41659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
41669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4167ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4168ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4169ba2698f1SMatthew G. Knepley     switch (pdepth) {
4170d71ae5a4SJacob Faibussowitsch     case 0:
4171d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4172d71ae5a4SJacob Faibussowitsch       break;
4173ba2698f1SMatthew G. Knepley     case 1:
4174ba2698f1SMatthew G. Knepley       switch (coneSize) {
4175d71ae5a4SJacob Faibussowitsch       case 2:
4176d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4177d71ae5a4SJacob Faibussowitsch         break;
4178d71ae5a4SJacob Faibussowitsch       case 3:
4179d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4180d71ae5a4SJacob Faibussowitsch         break;
4181ba2698f1SMatthew G. Knepley       case 4:
4182ba2698f1SMatthew G. Knepley         switch (dim) {
4183d71ae5a4SJacob Faibussowitsch         case 2:
4184d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4185d71ae5a4SJacob Faibussowitsch           break;
4186d71ae5a4SJacob Faibussowitsch         case 3:
4187d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4188d71ae5a4SJacob Faibussowitsch           break;
4189d71ae5a4SJacob Faibussowitsch         default:
4190d71ae5a4SJacob Faibussowitsch           break;
4191ba2698f1SMatthew G. Knepley         }
4192ba2698f1SMatthew G. Knepley         break;
4193d71ae5a4SJacob Faibussowitsch       case 5:
4194d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4195d71ae5a4SJacob Faibussowitsch         break;
4196d71ae5a4SJacob Faibussowitsch       case 6:
4197d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4198d71ae5a4SJacob Faibussowitsch         break;
4199d71ae5a4SJacob Faibussowitsch       case 8:
4200d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4201d71ae5a4SJacob Faibussowitsch         break;
4202d71ae5a4SJacob Faibussowitsch       default:
4203d71ae5a4SJacob Faibussowitsch         break;
4204ba2698f1SMatthew G. Knepley       }
4205ba2698f1SMatthew G. Knepley     }
4206ba2698f1SMatthew G. Knepley   } else {
4207ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4208ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4209ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4210ba2698f1SMatthew G. Knepley       switch (dim) {
4211ba2698f1SMatthew G. Knepley       case 1:
4212ba2698f1SMatthew G. Knepley         switch (coneSize) {
4213d71ae5a4SJacob Faibussowitsch         case 2:
4214d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4215d71ae5a4SJacob Faibussowitsch           break;
4216d71ae5a4SJacob Faibussowitsch         default:
4217d71ae5a4SJacob Faibussowitsch           break;
4218ba2698f1SMatthew G. Knepley         }
4219ba2698f1SMatthew G. Knepley         break;
4220ba2698f1SMatthew G. Knepley       case 2:
4221ba2698f1SMatthew G. Knepley         switch (coneSize) {
4222d71ae5a4SJacob Faibussowitsch         case 3:
4223d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4224d71ae5a4SJacob Faibussowitsch           break;
4225d71ae5a4SJacob Faibussowitsch         case 4:
4226d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4227d71ae5a4SJacob Faibussowitsch           break;
4228d71ae5a4SJacob Faibussowitsch         default:
4229d71ae5a4SJacob Faibussowitsch           break;
4230ba2698f1SMatthew G. Knepley         }
4231ba2698f1SMatthew G. Knepley         break;
4232ba2698f1SMatthew G. Knepley       case 3:
4233ba2698f1SMatthew G. Knepley         switch (coneSize) {
4234d71ae5a4SJacob Faibussowitsch         case 4:
4235d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4236d71ae5a4SJacob Faibussowitsch           break;
42379371c9d4SSatish Balay         case 5: {
4238da9060c4SMatthew G. Knepley           const PetscInt *cone;
4239da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4240da9060c4SMatthew G. Knepley 
42419566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
42429566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4243da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4244d71ae5a4SJacob Faibussowitsch           case 3:
4245d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4246d71ae5a4SJacob Faibussowitsch             break;
4247d71ae5a4SJacob Faibussowitsch           case 4:
4248d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4249d71ae5a4SJacob Faibussowitsch             break;
4250da9060c4SMatthew G. Knepley           }
42519371c9d4SSatish Balay         } break;
4252d71ae5a4SJacob Faibussowitsch         case 6:
4253d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4254d71ae5a4SJacob Faibussowitsch           break;
4255d71ae5a4SJacob Faibussowitsch         default:
4256d71ae5a4SJacob Faibussowitsch           break;
4257ba2698f1SMatthew G. Knepley         }
4258ba2698f1SMatthew G. Knepley         break;
4259d71ae5a4SJacob Faibussowitsch       default:
4260d71ae5a4SJacob Faibussowitsch         break;
4261ba2698f1SMatthew G. Knepley       }
4262ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4263ba2698f1SMatthew G. Knepley       switch (coneSize) {
4264d71ae5a4SJacob Faibussowitsch       case 2:
4265d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4266d71ae5a4SJacob Faibussowitsch         break;
4267d71ae5a4SJacob Faibussowitsch       case 3:
4268d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4269d71ae5a4SJacob Faibussowitsch         break;
4270d71ae5a4SJacob Faibussowitsch       case 4:
4271d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4272d71ae5a4SJacob Faibussowitsch         break;
4273d71ae5a4SJacob Faibussowitsch       default:
4274d71ae5a4SJacob Faibussowitsch         break;
4275ba2698f1SMatthew G. Knepley       }
4276ba2698f1SMatthew G. Knepley     }
4277ba2698f1SMatthew G. Knepley   }
4278412e9a14SMatthew G. Knepley   *pt = ct;
4279412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4280ba2698f1SMatthew G. Knepley }
4281412e9a14SMatthew G. Knepley 
4282412e9a14SMatthew G. Knepley /*@
4283412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4284412e9a14SMatthew G. Knepley 
4285412e9a14SMatthew G. Knepley   Collective on dm
4286412e9a14SMatthew G. Knepley 
4287412e9a14SMatthew G. Knepley   Input Parameter:
4288a1cb98faSBarry Smith . mesh - The `DMPLEX`
4289412e9a14SMatthew G. Knepley 
4290412e9a14SMatthew G. Knepley   Level: developer
4291412e9a14SMatthew G. Knepley 
4292a1cb98faSBarry Smith   Note:
4293a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4294a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4295a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4296412e9a14SMatthew G. Knepley 
4297a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4298a1cb98faSBarry Smith 
4299a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4300412e9a14SMatthew G. Knepley @*/
4301d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4302d71ae5a4SJacob Faibussowitsch {
4303412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4304412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4305412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4306412e9a14SMatthew G. Knepley 
4307412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4308412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4309412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
43109566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
43119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
43129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4313412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4314327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4315412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4316412e9a14SMatthew G. Knepley 
43179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
43189566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
431963a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
43209566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4321412e9a14SMatthew G. Knepley   }
43229566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
43239566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
4324ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4325ba2698f1SMatthew G. Knepley }
4326ba2698f1SMatthew G. Knepley 
4327552f7358SJed Brown /*@C
4328552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4329552f7358SJed Brown 
4330552f7358SJed Brown   Not Collective
4331552f7358SJed Brown 
4332552f7358SJed Brown   Input Parameters:
4333a1cb98faSBarry Smith + dm - The `DMPLEX` object
4334552f7358SJed Brown . numPoints - The number of input points for the join
4335552f7358SJed Brown - points - The input points
4336552f7358SJed Brown 
4337552f7358SJed Brown   Output Parameters:
4338552f7358SJed Brown + numCoveredPoints - The number of points in the join
4339552f7358SJed Brown - coveredPoints - The points in the join
4340552f7358SJed Brown 
4341552f7358SJed Brown   Level: intermediate
4342552f7358SJed Brown 
4343a1cb98faSBarry Smith   Note:
4344a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4345552f7358SJed Brown 
4346a1cb98faSBarry Smith   Fortran Note:
4347a1cb98faSBarry Smith   The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array.
43483813dfbdSMatthew G Knepley 
4349a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4350552f7358SJed Brown @*/
4351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4352d71ae5a4SJacob Faibussowitsch {
4353552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4354552f7358SJed Brown   PetscInt *join[2];
4355552f7358SJed Brown   PetscInt  joinSize, i = 0;
4356552f7358SJed Brown   PetscInt  dof, off, p, c, m;
43576302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4358552f7358SJed Brown 
4359552f7358SJed Brown   PetscFunctionBegin;
4360552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
436148bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
436248bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
436348bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
43646302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
43656302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
43666302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4367552f7358SJed Brown   /* Copy in support of first point */
43689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
43699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4370ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4371552f7358SJed Brown   /* Check each successive support */
4372552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4373552f7358SJed Brown     PetscInt newJoinSize = 0;
4374552f7358SJed Brown 
43759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
43769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4377552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4378552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4379552f7358SJed Brown 
4380552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4381552f7358SJed Brown         if (point == join[i][m]) {
4382552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4383552f7358SJed Brown           break;
4384552f7358SJed Brown         }
4385552f7358SJed Brown       }
4386552f7358SJed Brown     }
4387552f7358SJed Brown     joinSize = newJoinSize;
4388552f7358SJed Brown     i        = 1 - i;
4389552f7358SJed Brown   }
4390552f7358SJed Brown   *numCoveredPoints = joinSize;
4391552f7358SJed Brown   *coveredPoints    = join[i];
43926302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
4393552f7358SJed Brown   PetscFunctionReturn(0);
4394552f7358SJed Brown }
4395552f7358SJed Brown 
4396552f7358SJed Brown /*@C
4397552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4398552f7358SJed Brown 
4399552f7358SJed Brown   Not Collective
4400552f7358SJed Brown 
4401552f7358SJed Brown   Input Parameters:
4402a1cb98faSBarry Smith + dm - The `DMPLEX` object
4403552f7358SJed Brown . numPoints - The number of input points for the join
4404552f7358SJed Brown - points - The input points
4405552f7358SJed Brown 
4406552f7358SJed Brown   Output Parameters:
4407552f7358SJed Brown + numCoveredPoints - The number of points in the join
4408552f7358SJed Brown - coveredPoints - The points in the join
4409552f7358SJed Brown 
4410552f7358SJed Brown   Level: intermediate
4411552f7358SJed Brown 
4412a1cb98faSBarry Smith   Fortran Note:
4413a1cb98faSBarry Smith   The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array.
4414a1cb98faSBarry Smith 
4415a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4416552f7358SJed Brown @*/
4417d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4418d71ae5a4SJacob Faibussowitsch {
4419552f7358SJed Brown   PetscFunctionBegin;
4420552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4421d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4422d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4423d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
44249566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4425d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4426552f7358SJed Brown   PetscFunctionReturn(0);
4427552f7358SJed Brown }
4428552f7358SJed Brown 
4429552f7358SJed Brown /*@C
4430552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4431552f7358SJed Brown 
4432552f7358SJed Brown   Not Collective
4433552f7358SJed Brown 
4434552f7358SJed Brown   Input Parameters:
4435a1cb98faSBarry Smith + dm - The `DMPLEX` object
4436552f7358SJed Brown . numPoints - The number of input points for the join
4437552f7358SJed Brown - points - The input points
4438552f7358SJed Brown 
4439552f7358SJed Brown   Output Parameters:
4440552f7358SJed Brown + numCoveredPoints - The number of points in the join
4441552f7358SJed Brown - coveredPoints - The points in the join
4442552f7358SJed Brown 
4443552f7358SJed Brown   Level: intermediate
4444552f7358SJed Brown 
4445a1cb98faSBarry Smith   Fortran Note:
4446a1cb98faSBarry Smith   The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array.
4447a1cb98faSBarry Smith 
4448a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4449552f7358SJed Brown @*/
4450d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4451d71ae5a4SJacob Faibussowitsch {
4452552f7358SJed Brown   PetscInt *offsets, **closures;
4453552f7358SJed Brown   PetscInt *join[2];
4454552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
445524c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4456552f7358SJed Brown 
4457552f7358SJed Brown   PetscFunctionBegin;
4458552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
445948bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
446048bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
446148bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4462552f7358SJed Brown 
44639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
44649566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
44659566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
44666302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
446724c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
44689566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
44699566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4470552f7358SJed Brown 
4471552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4472552f7358SJed Brown     PetscInt closureSize;
4473552f7358SJed Brown 
44749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
44750d644c17SKarl Rupp 
4476552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4477552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4478552f7358SJed Brown       PetscInt pStart, pEnd, i;
4479552f7358SJed Brown 
44809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4481552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4482552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4483552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4484552f7358SJed Brown           break;
4485552f7358SJed Brown         }
4486552f7358SJed Brown       }
4487552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4488552f7358SJed Brown     }
448963a3b9bcSJacob 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);
4490552f7358SJed Brown   }
4491552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4492552f7358SJed Brown     PetscInt dof;
4493552f7358SJed Brown 
4494552f7358SJed Brown     /* Copy in support of first point */
4495552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4496ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4497552f7358SJed Brown     /* Check each successive cone */
4498552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4499552f7358SJed Brown       PetscInt newJoinSize = 0;
4500552f7358SJed Brown 
4501552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4502552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4503552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4504552f7358SJed Brown 
4505552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4506552f7358SJed Brown           if (point == join[i][m]) {
4507552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4508552f7358SJed Brown             break;
4509552f7358SJed Brown           }
4510552f7358SJed Brown         }
4511552f7358SJed Brown       }
4512552f7358SJed Brown       joinSize = newJoinSize;
4513552f7358SJed Brown       i        = 1 - i;
4514552f7358SJed Brown     }
4515552f7358SJed Brown     if (joinSize) break;
4516552f7358SJed Brown   }
4517552f7358SJed Brown   *numCoveredPoints = joinSize;
4518552f7358SJed Brown   *coveredPoints    = join[i];
451948a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
45209566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45219566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
45226302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
4523552f7358SJed Brown   PetscFunctionReturn(0);
4524552f7358SJed Brown }
4525552f7358SJed Brown 
4526552f7358SJed Brown /*@C
4527552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4528552f7358SJed Brown 
4529552f7358SJed Brown   Not Collective
4530552f7358SJed Brown 
4531552f7358SJed Brown   Input Parameters:
4532a1cb98faSBarry Smith + dm - The `DMPLEX` object
4533552f7358SJed Brown . numPoints - The number of input points for the meet
4534552f7358SJed Brown - points - The input points
4535552f7358SJed Brown 
4536552f7358SJed Brown   Output Parameters:
4537552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4538552f7358SJed Brown - coveredPoints - The points in the meet
4539552f7358SJed Brown 
4540552f7358SJed Brown   Level: intermediate
4541552f7358SJed Brown 
4542a1cb98faSBarry Smith   Note:
4543a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4544552f7358SJed Brown 
45453813dfbdSMatthew G Knepley   Fortran Notes:
4546a1cb98faSBarry Smith   The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array.
45473813dfbdSMatthew G Knepley 
4548a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4549552f7358SJed Brown @*/
4550d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4551d71ae5a4SJacob Faibussowitsch {
4552552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4553552f7358SJed Brown   PetscInt *meet[2];
4554552f7358SJed Brown   PetscInt  meetSize, i = 0;
4555552f7358SJed Brown   PetscInt  dof, off, p, c, m;
45566302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4557552f7358SJed Brown 
4558552f7358SJed Brown   PetscFunctionBegin;
4559552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4560dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4561dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4562064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
45636302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
45646302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
45656302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4566552f7358SJed Brown   /* Copy in cone of first point */
45679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
45689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4569ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4570552f7358SJed Brown   /* Check each successive cone */
4571552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4572552f7358SJed Brown     PetscInt newMeetSize = 0;
4573552f7358SJed Brown 
45749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
45759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4576552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4577552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4578552f7358SJed Brown 
4579552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4580552f7358SJed Brown         if (point == meet[i][m]) {
4581552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4582552f7358SJed Brown           break;
4583552f7358SJed Brown         }
4584552f7358SJed Brown       }
4585552f7358SJed Brown     }
4586552f7358SJed Brown     meetSize = newMeetSize;
4587552f7358SJed Brown     i        = 1 - i;
4588552f7358SJed Brown   }
4589552f7358SJed Brown   *numCoveringPoints = meetSize;
4590552f7358SJed Brown   *coveringPoints    = meet[i];
45916302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
4592552f7358SJed Brown   PetscFunctionReturn(0);
4593552f7358SJed Brown }
4594552f7358SJed Brown 
4595552f7358SJed Brown /*@C
4596552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4597552f7358SJed Brown 
4598552f7358SJed Brown   Not Collective
4599552f7358SJed Brown 
4600552f7358SJed Brown   Input Parameters:
4601a1cb98faSBarry Smith + dm - The `DMPLEX` object
4602552f7358SJed Brown . numPoints - The number of input points for the meet
4603552f7358SJed Brown - points - The input points
4604552f7358SJed Brown 
4605552f7358SJed Brown   Output Parameters:
4606552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4607552f7358SJed Brown - coveredPoints - The points in the meet
4608552f7358SJed Brown 
4609552f7358SJed Brown   Level: intermediate
4610552f7358SJed Brown 
4611a1cb98faSBarry Smith   Fortran Note:
4612a1cb98faSBarry Smith   The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array.
46133813dfbdSMatthew G Knepley 
4614a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4615552f7358SJed Brown @*/
4616d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4617d71ae5a4SJacob Faibussowitsch {
4618552f7358SJed Brown   PetscFunctionBegin;
4619552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4620d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4621d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4622d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
46239566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4624d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4625552f7358SJed Brown   PetscFunctionReturn(0);
4626552f7358SJed Brown }
4627552f7358SJed Brown 
4628552f7358SJed Brown /*@C
4629552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4630552f7358SJed Brown 
4631552f7358SJed Brown   Not Collective
4632552f7358SJed Brown 
4633552f7358SJed Brown   Input Parameters:
4634a1cb98faSBarry Smith + dm - The `DMPLEX` object
4635552f7358SJed Brown . numPoints - The number of input points for the meet
4636552f7358SJed Brown - points - The input points
4637552f7358SJed Brown 
4638552f7358SJed Brown   Output Parameters:
4639552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4640552f7358SJed Brown - coveredPoints - The points in the meet
4641552f7358SJed Brown 
4642552f7358SJed Brown   Level: intermediate
4643552f7358SJed Brown 
4644a1cb98faSBarry Smith   Fortran Note:
4645a1cb98faSBarry Smith   The numCoveredPoints argument is not present in the Fortran binding since it is internal to the array.
46463813dfbdSMatthew G Knepley 
4647a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4648552f7358SJed Brown @*/
4649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4650d71ae5a4SJacob Faibussowitsch {
4651552f7358SJed Brown   PetscInt *offsets, **closures;
4652552f7358SJed Brown   PetscInt *meet[2];
4653552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
465424c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4655552f7358SJed Brown 
4656552f7358SJed Brown   PetscFunctionBegin;
4657552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4658dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4659dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4660064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4661552f7358SJed Brown 
46629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
46639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
46649566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
46656302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
466624c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
46679566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
46689566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4669552f7358SJed Brown 
4670552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4671552f7358SJed Brown     PetscInt closureSize;
4672552f7358SJed Brown 
46739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
46740d644c17SKarl Rupp 
4675552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4676552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4677552f7358SJed Brown       PetscInt pStart, pEnd, i;
4678552f7358SJed Brown 
46799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4680552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4681552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4682552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4683552f7358SJed Brown           break;
4684552f7358SJed Brown         }
4685552f7358SJed Brown       }
4686552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4687552f7358SJed Brown     }
468863a3b9bcSJacob 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);
4689552f7358SJed Brown   }
4690552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4691552f7358SJed Brown     PetscInt dof;
4692552f7358SJed Brown 
4693552f7358SJed Brown     /* Copy in cone of first point */
4694552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
4695ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
4696552f7358SJed Brown     /* Check each successive cone */
4697552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4698552f7358SJed Brown       PetscInt newMeetSize = 0;
4699552f7358SJed Brown 
4700552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
4701552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4702552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
4703552f7358SJed Brown 
4704552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4705552f7358SJed Brown           if (point == meet[i][m]) {
4706552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
4707552f7358SJed Brown             break;
4708552f7358SJed Brown           }
4709552f7358SJed Brown         }
4710552f7358SJed Brown       }
4711552f7358SJed Brown       meetSize = newMeetSize;
4712552f7358SJed Brown       i        = 1 - i;
4713552f7358SJed Brown     }
4714552f7358SJed Brown     if (meetSize) break;
4715552f7358SJed Brown   }
4716552f7358SJed Brown   *numCoveredPoints = meetSize;
4717552f7358SJed Brown   *coveredPoints    = meet[i];
471848a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
47199566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
47209566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
47216302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
4722552f7358SJed Brown   PetscFunctionReturn(0);
4723552f7358SJed Brown }
4724552f7358SJed Brown 
47254e3744c5SMatthew G. Knepley /*@C
4726a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
47274e3744c5SMatthew G. Knepley 
47284e3744c5SMatthew G. Knepley   Not Collective
47294e3744c5SMatthew G. Knepley 
47304e3744c5SMatthew G. Knepley   Input Parameters:
4731a1cb98faSBarry Smith + dmA - A `DMPLEX` object
4732a1cb98faSBarry Smith - dmB - A `DMPLEX` object
47334e3744c5SMatthew G. Knepley 
47344e3744c5SMatthew G. Knepley   Output Parameters:
4735a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
47364e3744c5SMatthew G. Knepley 
47374e3744c5SMatthew G. Knepley   Level: intermediate
47384e3744c5SMatthew G. Knepley 
4739a1cb98faSBarry Smith   Note:
47403c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
47414e3744c5SMatthew G. Knepley 
4742a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
47434e3744c5SMatthew G. Knepley @*/
4744d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
4745d71ae5a4SJacob Faibussowitsch {
47464e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
47474e3744c5SMatthew G. Knepley 
47484e3744c5SMatthew G. Knepley   PetscFunctionBegin;
47494e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
47504e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4751dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
47524e3744c5SMatthew G. Knepley 
47534e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
47549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
47559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
47564e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
47579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
47589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
47594e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
47604e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
47614e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
47624e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
47634e3744c5SMatthew G. Knepley 
47649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
47659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
47669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
47679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
47689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
47699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
47704e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
47714e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
47724e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
47734e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
47744e3744c5SMatthew G. Knepley     }
47759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
47769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
47779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
47789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
47794e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
47804e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
47814e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
47824e3744c5SMatthew G. Knepley     }
47834e3744c5SMatthew G. Knepley   }
47844e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
47854e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
47864e3744c5SMatthew G. Knepley }
47874e3744c5SMatthew G. Knepley 
47887cd05799SMatthew G. Knepley /*@C
47897cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
47907cd05799SMatthew G. Knepley 
47917cd05799SMatthew G. Knepley   Not Collective
47927cd05799SMatthew G. Knepley 
47937cd05799SMatthew G. Knepley   Input Parameters:
4794a1cb98faSBarry Smith + dm         - The `DMPLEX`
47957cd05799SMatthew G. Knepley . cellDim    - The cell dimension
47967cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
47977cd05799SMatthew G. Knepley 
47987cd05799SMatthew G. Knepley   Output Parameters:
47997cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
48007cd05799SMatthew G. Knepley 
48017cd05799SMatthew G. Knepley   Level: developer
48027cd05799SMatthew G. Knepley 
4803a1cb98faSBarry Smith   Note:
48047cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
48057cd05799SMatthew G. Knepley 
4806a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
48077cd05799SMatthew G. Knepley @*/
4808d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4809d71ae5a4SJacob Faibussowitsch {
481082f516ccSBarry Smith   MPI_Comm comm;
4811552f7358SJed Brown 
4812552f7358SJed Brown   PetscFunctionBegin;
48139566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4814dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices, 4);
4815552f7358SJed Brown   switch (cellDim) {
4816d71ae5a4SJacob Faibussowitsch   case 0:
4817d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
4818d71ae5a4SJacob Faibussowitsch     break;
4819d71ae5a4SJacob Faibussowitsch   case 1:
4820d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
4821d71ae5a4SJacob Faibussowitsch     break;
4822552f7358SJed Brown   case 2:
4823552f7358SJed Brown     switch (numCorners) {
482419436ca2SJed Brown     case 3:                 /* triangle */
482519436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4826552f7358SJed Brown       break;
482719436ca2SJed Brown     case 4:                 /* quadrilateral */
482819436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4829552f7358SJed Brown       break;
483019436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
483119436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4832552f7358SJed Brown       break;
483319436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
483419436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4835552f7358SJed Brown       break;
4836d71ae5a4SJacob Faibussowitsch     default:
4837d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4838552f7358SJed Brown     }
4839552f7358SJed Brown     break;
4840552f7358SJed Brown   case 3:
4841552f7358SJed Brown     switch (numCorners) {
484219436ca2SJed Brown     case 4:                 /* tetradehdron */
484319436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4844552f7358SJed Brown       break;
484519436ca2SJed Brown     case 6:                 /* tet cohesive cells */
484619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4847552f7358SJed Brown       break;
484819436ca2SJed Brown     case 8:                 /* hexahedron */
484919436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4850552f7358SJed Brown       break;
485119436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
485219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4853552f7358SJed Brown       break;
485419436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
485519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4856552f7358SJed Brown       break;
485719436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
485819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4859552f7358SJed Brown       break;
486019436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
486119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4862552f7358SJed Brown       break;
486319436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
486419436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4865552f7358SJed Brown       break;
4866d71ae5a4SJacob Faibussowitsch     default:
4867d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4868552f7358SJed Brown     }
4869552f7358SJed Brown     break;
4870d71ae5a4SJacob Faibussowitsch   default:
4871d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4872552f7358SJed Brown   }
4873552f7358SJed Brown   PetscFunctionReturn(0);
4874552f7358SJed Brown }
4875552f7358SJed Brown 
4876552f7358SJed Brown /*@
4877a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
4878552f7358SJed Brown 
4879552f7358SJed Brown   Not Collective
4880552f7358SJed Brown 
4881aa50250dSMatthew G. Knepley   Input Parameter:
4882a1cb98faSBarry Smith . dm    - The `DMPLEX` object
4883552f7358SJed Brown 
4884aa50250dSMatthew G. Knepley   Output Parameter:
4885a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
4886552f7358SJed Brown 
4887552f7358SJed Brown   Level: developer
4888552f7358SJed Brown 
4889a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4890aa50250dSMatthew G. Knepley @*/
4891d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4892d71ae5a4SJacob Faibussowitsch {
4893aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4894aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4895aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4896c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4897aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4898aa50250dSMatthew G. Knepley }
4899aa50250dSMatthew G. Knepley 
4900aa50250dSMatthew G. Knepley /*@
4901aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4902aa50250dSMatthew G. Knepley 
4903aa50250dSMatthew G. Knepley   Not Collective
4904aa50250dSMatthew G. Knepley 
4905aa50250dSMatthew G. Knepley   Input Parameter:
4906a1cb98faSBarry Smith . dm    - The `DMPLEX` object
4907aa50250dSMatthew G. Knepley 
4908aa50250dSMatthew G. Knepley   Output Parameter:
4909aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4910aa50250dSMatthew G. Knepley 
4911aa50250dSMatthew G. Knepley   Level: developer
4912552f7358SJed Brown 
4913b1bb481bSMatthew Knepley   Notes:
4914a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
4915a1cb98faSBarry Smith 
4916a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
4917a1cb98faSBarry Smith 
4918dc287ab2SVaclav Hapla   An empty mesh gives -1.
4919b1bb481bSMatthew Knepley 
4920a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4921552f7358SJed Brown @*/
4922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4923d71ae5a4SJacob Faibussowitsch {
49249f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4925aa50250dSMatthew G. Knepley   DMLabel  label;
4926aa50250dSMatthew G. Knepley   PetscInt d = 0;
4927552f7358SJed Brown 
4928552f7358SJed Brown   PetscFunctionBegin;
4929552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4930dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
49319f4ada15SMatthew G. Knepley   if (mesh->tr) {
49329f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
49339f4ada15SMatthew G. Knepley   } else {
49349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
49359566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
4936552f7358SJed Brown     *depth = d - 1;
49379f4ada15SMatthew G. Knepley   }
4938552f7358SJed Brown   PetscFunctionReturn(0);
4939552f7358SJed Brown }
4940552f7358SJed Brown 
4941552f7358SJed Brown /*@
4942552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4943552f7358SJed Brown 
4944552f7358SJed Brown   Not Collective
4945552f7358SJed Brown 
4946552f7358SJed Brown   Input Parameters:
4947a1cb98faSBarry Smith + dm    - The `DMPLEX` object
4948570fa34dSVaclav Hapla - depth - The requested depth
4949552f7358SJed Brown 
4950552f7358SJed Brown   Output Parameters:
4951552f7358SJed Brown + start - The first point at this depth
4952552f7358SJed Brown - end   - One beyond the last point at this depth
4953552f7358SJed Brown 
4954552f7358SJed Brown   Level: developer
4955552f7358SJed Brown 
4956a1cb98faSBarry Smith   Notes:
4957a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4958a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
4959a1cb98faSBarry Smith   higher dimension, e.g., "edges".
4960a1cb98faSBarry Smith 
4961a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4962552f7358SJed Brown @*/
4963d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
4964d71ae5a4SJacob Faibussowitsch {
49659f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4966aa50250dSMatthew G. Knepley   DMLabel  label;
496763d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
4968552f7358SJed Brown 
4969552f7358SJed Brown   PetscFunctionBegin;
4970552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49719371c9d4SSatish Balay   if (start) {
49729371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
49739371c9d4SSatish Balay     *start = 0;
49749371c9d4SSatish Balay   }
49759371c9d4SSatish Balay   if (end) {
49769371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
49779371c9d4SSatish Balay     *end = 0;
49789371c9d4SSatish Balay   }
49799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
49800d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4981570fa34dSVaclav Hapla   if (depth < 0) {
498263d1a920SMatthew G. Knepley     if (start) *start = pStart;
498363d1a920SMatthew G. Knepley     if (end) *end = pEnd;
498463d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4985552f7358SJed Brown   }
49869f4ada15SMatthew G. Knepley   if (mesh->tr) {
49879f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
49889f4ada15SMatthew G. Knepley   } else {
49899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
499028b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
4991570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
49929f4ada15SMatthew G. Knepley   }
4993552f7358SJed Brown   PetscFunctionReturn(0);
4994552f7358SJed Brown }
4995552f7358SJed Brown 
4996552f7358SJed Brown /*@
4997552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4998552f7358SJed Brown 
4999552f7358SJed Brown   Not Collective
5000552f7358SJed Brown 
5001552f7358SJed Brown   Input Parameters:
5002a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5003570fa34dSVaclav Hapla - height - The requested height
5004552f7358SJed Brown 
5005552f7358SJed Brown   Output Parameters:
5006552f7358SJed Brown + start - The first point at this height
5007552f7358SJed Brown - end   - One beyond the last point at this height
5008552f7358SJed Brown 
5009552f7358SJed Brown   Level: developer
5010552f7358SJed Brown 
5011a1cb98faSBarry Smith   Notes:
5012a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5013a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5014a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5015a1cb98faSBarry Smith 
5016a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5017552f7358SJed Brown @*/
5018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5019d71ae5a4SJacob Faibussowitsch {
5020aa50250dSMatthew G. Knepley   DMLabel  label;
502163d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5022552f7358SJed Brown 
5023552f7358SJed Brown   PetscFunctionBegin;
5024552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50259371c9d4SSatish Balay   if (start) {
50269371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
50279371c9d4SSatish Balay     *start = 0;
50289371c9d4SSatish Balay   }
50299371c9d4SSatish Balay   if (end) {
50309371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
50319371c9d4SSatish Balay     *end = 0;
50329371c9d4SSatish Balay   }
50339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
50340d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
5035570fa34dSVaclav Hapla   if (height < 0) {
503663d1a920SMatthew G. Knepley     if (start) *start = pStart;
503763d1a920SMatthew G. Knepley     if (end) *end = pEnd;
503863d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
5039552f7358SJed Brown   }
50409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
504128b400f6SJacob Faibussowitsch   PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
50429566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
5043570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth - 1 - height, start, end));
5044552f7358SJed Brown   PetscFunctionReturn(0);
5045552f7358SJed Brown }
5046552f7358SJed Brown 
5047ba2698f1SMatthew G. Knepley /*@
5048ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
5049ba2698f1SMatthew G. Knepley 
5050ba2698f1SMatthew G. Knepley   Not Collective
5051ba2698f1SMatthew G. Knepley 
5052d8d19677SJose E. Roman   Input Parameters:
5053a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5054ba2698f1SMatthew G. Knepley - point - The point
5055ba2698f1SMatthew G. Knepley 
5056ba2698f1SMatthew G. Knepley   Output Parameter:
5057ba2698f1SMatthew G. Knepley . depth - The depth of the point
5058ba2698f1SMatthew G. Knepley 
5059ba2698f1SMatthew G. Knepley   Level: intermediate
5060ba2698f1SMatthew G. Knepley 
5061a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5062ba2698f1SMatthew G. Knepley @*/
5063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5064d71ae5a4SJacob Faibussowitsch {
5065ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5066ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
506740a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
50689566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
5069ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
5070ba2698f1SMatthew G. Knepley }
5071ba2698f1SMatthew G. Knepley 
5072ba2698f1SMatthew G. Knepley /*@
50730c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
50740c0a32dcSVaclav Hapla 
50750c0a32dcSVaclav Hapla   Not Collective
50760c0a32dcSVaclav Hapla 
5077d8d19677SJose E. Roman   Input Parameters:
5078a1cb98faSBarry Smith + dm    - The `DMPLEX` object
50790c0a32dcSVaclav Hapla - point - The point
50800c0a32dcSVaclav Hapla 
50810c0a32dcSVaclav Hapla   Output Parameter:
50820c0a32dcSVaclav Hapla . height - The height of the point
50830c0a32dcSVaclav Hapla 
50840c0a32dcSVaclav Hapla   Level: intermediate
50850c0a32dcSVaclav Hapla 
5086a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
50870c0a32dcSVaclav Hapla @*/
5088d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5089d71ae5a4SJacob Faibussowitsch {
50900c0a32dcSVaclav Hapla   PetscInt n, pDepth;
50910c0a32dcSVaclav Hapla 
50920c0a32dcSVaclav Hapla   PetscFunctionBegin;
50930c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50940c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
50959566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
50969566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
50970c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
50980c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
50990c0a32dcSVaclav Hapla }
51000c0a32dcSVaclav Hapla 
51010c0a32dcSVaclav Hapla /*@
5102a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5103ba2698f1SMatthew G. Knepley 
5104ba2698f1SMatthew G. Knepley   Not Collective
5105ba2698f1SMatthew G. Knepley 
5106ba2698f1SMatthew G. Knepley   Input Parameter:
5107a1cb98faSBarry Smith . dm - The `DMPLEX` object
5108ba2698f1SMatthew G. Knepley 
5109ba2698f1SMatthew G. Knepley   Output Parameter:
5110a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5111412e9a14SMatthew G. Knepley 
5112ba2698f1SMatthew G. Knepley   Level: developer
5113ba2698f1SMatthew G. Knepley 
5114a1cb98faSBarry Smith   Note:
5115a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5116a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5117a1cb98faSBarry Smith 
5118a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5119ba2698f1SMatthew G. Knepley @*/
5120d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5121d71ae5a4SJacob Faibussowitsch {
5122ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5123ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5124ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
51259566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5126ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
5127ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
5128ba2698f1SMatthew G. Knepley }
5129ba2698f1SMatthew G. Knepley 
5130ba2698f1SMatthew G. Knepley /*@
5131ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5132ba2698f1SMatthew G. Knepley 
5133ba2698f1SMatthew G. Knepley   Not Collective
5134ba2698f1SMatthew G. Knepley 
5135d8d19677SJose E. Roman   Input Parameters:
5136a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5137ba2698f1SMatthew G. Knepley - cell - The cell
5138ba2698f1SMatthew G. Knepley 
5139ba2698f1SMatthew G. Knepley   Output Parameter:
5140ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5141ba2698f1SMatthew G. Knepley 
5142ba2698f1SMatthew G. Knepley   Level: intermediate
5143ba2698f1SMatthew G. Knepley 
5144a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5145ba2698f1SMatthew G. Knepley @*/
5146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5147d71ae5a4SJacob Faibussowitsch {
51489f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5149ba2698f1SMatthew G. Knepley   DMLabel  label;
5150ba2698f1SMatthew G. Knepley   PetscInt ct;
5151ba2698f1SMatthew G. Knepley 
5152ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5153ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5154ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
51559f4ada15SMatthew G. Knepley   if (mesh->tr) {
51569f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
51579f4ada15SMatthew G. Knepley   } else {
51589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
51599566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, cell, &ct));
516063a3b9bcSJacob Faibussowitsch     PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5161ba2698f1SMatthew G. Knepley     *celltype = (DMPolytopeType)ct;
51629f4ada15SMatthew G. Knepley   }
5163ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
5164ba2698f1SMatthew G. Knepley }
5165ba2698f1SMatthew G. Knepley 
5166412e9a14SMatthew G. Knepley /*@
5167412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5168412e9a14SMatthew G. Knepley 
5169412e9a14SMatthew G. Knepley   Not Collective
5170412e9a14SMatthew G. Knepley 
5171412e9a14SMatthew G. Knepley   Input Parameters:
5172a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5173412e9a14SMatthew G. Knepley . cell - The cell
5174412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5175412e9a14SMatthew G. Knepley 
5176a1cb98faSBarry Smith   Level: advanced
5177a1cb98faSBarry Smith 
5178a1cb98faSBarry Smith   Note:
5179a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5180412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5181412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5182412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
5183412e9a14SMatthew G. Knepley 
5184a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5185412e9a14SMatthew G. Knepley @*/
5186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5187d71ae5a4SJacob Faibussowitsch {
5188412e9a14SMatthew G. Knepley   DMLabel label;
5189412e9a14SMatthew G. Knepley 
5190412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5191412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
51939566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
5194412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
5195412e9a14SMatthew G. Knepley }
5196412e9a14SMatthew G. Knepley 
5197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5198d71ae5a4SJacob Faibussowitsch {
5199efe440bfSMatthew G. Knepley   PetscSection section, s;
5200efe440bfSMatthew G. Knepley   Mat          m;
52013e922f36SToby Isaac   PetscInt     maxHeight;
5202dd4c3f67SMatthew G. Knepley   const char  *prefix;
5203552f7358SJed Brown 
5204552f7358SJed Brown   PetscFunctionBegin;
52059566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5206dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5207dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5208dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
52099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
52109566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
52119566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
52129566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
52139566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
52149566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
52159566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
52169566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
52179566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
52189566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
52198f4c458bSMatthew G. Knepley 
52209566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
52219566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5222dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5223dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
5224552f7358SJed Brown   PetscFunctionReturn(0);
5225552f7358SJed Brown }
5226552f7358SJed Brown 
5227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5228d71ae5a4SJacob Faibussowitsch {
52296858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
52306858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5231f19dbd58SToby Isaac 
5232f19dbd58SToby Isaac   PetscFunctionBegin;
5233f19dbd58SToby Isaac   *field = NULL;
52349566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
52359566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
52366858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
52376858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5238f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
52396858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
52406858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5241f19dbd58SToby Isaac   }
5242f19dbd58SToby Isaac   PetscFunctionReturn(0);
5243f19dbd58SToby Isaac }
5244f19dbd58SToby Isaac 
52457cd05799SMatthew G. Knepley /*@C
52467cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
52477cd05799SMatthew G. Knepley 
52487cd05799SMatthew G. Knepley   Not Collective
52497cd05799SMatthew G. Knepley 
52507cd05799SMatthew G. Knepley   Input Parameters:
5251a1cb98faSBarry Smith . dm        - The `DMPLEX` object
52527cd05799SMatthew G. Knepley 
52537cd05799SMatthew G. Knepley   Output Parameter:
5254a1cb98faSBarry Smith . section - The `PetscSection` object
52557cd05799SMatthew G. Knepley 
52567cd05799SMatthew G. Knepley   Level: developer
52577cd05799SMatthew G. Knepley 
5258a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
52597cd05799SMatthew G. Knepley @*/
5260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5261d71ae5a4SJacob Faibussowitsch {
5262552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5263552f7358SJed Brown 
5264552f7358SJed Brown   PetscFunctionBegin;
5265552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5266552f7358SJed Brown   if (section) *section = mesh->coneSection;
5267552f7358SJed Brown   PetscFunctionReturn(0);
5268552f7358SJed Brown }
5269552f7358SJed Brown 
52707cd05799SMatthew G. Knepley /*@C
52717cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
52727cd05799SMatthew G. Knepley 
52737cd05799SMatthew G. Knepley   Not Collective
52747cd05799SMatthew G. Knepley 
52757cd05799SMatthew G. Knepley   Input Parameters:
5276a1cb98faSBarry Smith . dm        - The `DMPLEX` object
52777cd05799SMatthew G. Knepley 
52787cd05799SMatthew G. Knepley   Output Parameter:
5279a1cb98faSBarry Smith . section - The `PetscSection` object
52807cd05799SMatthew G. Knepley 
52817cd05799SMatthew G. Knepley   Level: developer
52827cd05799SMatthew G. Knepley 
5283a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
52847cd05799SMatthew G. Knepley @*/
5285d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5286d71ae5a4SJacob Faibussowitsch {
52878cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
52888cb4d582SMatthew G. Knepley 
52898cb4d582SMatthew G. Knepley   PetscFunctionBegin;
52908cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52918cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
52928cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
52938cb4d582SMatthew G. Knepley }
52948cb4d582SMatthew G. Knepley 
52957cd05799SMatthew G. Knepley /*@C
52967cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
52977cd05799SMatthew G. Knepley 
52987cd05799SMatthew G. Knepley   Not Collective
52997cd05799SMatthew G. Knepley 
53007cd05799SMatthew G. Knepley   Input Parameters:
5301a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53027cd05799SMatthew G. Knepley 
53037cd05799SMatthew G. Knepley   Output Parameter:
53047cd05799SMatthew G. Knepley . cones - The cone for each point
53057cd05799SMatthew G. Knepley 
53067cd05799SMatthew G. Knepley   Level: developer
53077cd05799SMatthew G. Knepley 
5308a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
53097cd05799SMatthew G. Knepley @*/
5310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5311d71ae5a4SJacob Faibussowitsch {
5312552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5313552f7358SJed Brown 
5314552f7358SJed Brown   PetscFunctionBegin;
5315552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5316552f7358SJed Brown   if (cones) *cones = mesh->cones;
5317552f7358SJed Brown   PetscFunctionReturn(0);
5318552f7358SJed Brown }
5319552f7358SJed Brown 
53207cd05799SMatthew G. Knepley /*@C
53217cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
53227cd05799SMatthew G. Knepley 
53237cd05799SMatthew G. Knepley   Not Collective
53247cd05799SMatthew G. Knepley 
53257cd05799SMatthew G. Knepley   Input Parameters:
5326a1cb98faSBarry Smith . dm        - The `DMPLEX` object
53277cd05799SMatthew G. Knepley 
53287cd05799SMatthew G. Knepley   Output Parameter:
5329b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
53307cd05799SMatthew G. Knepley 
53317cd05799SMatthew G. Knepley   Level: developer
53327cd05799SMatthew G. Knepley 
5333b5a892a1SMatthew G. Knepley   Notes:
5334a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5335b5a892a1SMatthew G. Knepley 
5336a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5337b5a892a1SMatthew G. Knepley 
5338a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
53397cd05799SMatthew G. Knepley @*/
5340d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5341d71ae5a4SJacob Faibussowitsch {
5342552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5343552f7358SJed Brown 
5344552f7358SJed Brown   PetscFunctionBegin;
5345552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5346552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5347552f7358SJed Brown   PetscFunctionReturn(0);
5348552f7358SJed Brown }
5349552f7358SJed Brown 
5350552f7358SJed Brown /******************************** FEM Support **********************************/
5351552f7358SJed Brown 
53529e8305c2SJed Brown /*
53539e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
53549e8305c2SJed Brown  representing a line in the section.
53559e8305c2SJed Brown */
5356d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k)
5357d71ae5a4SJacob Faibussowitsch {
53589e8305c2SJed Brown   PetscFunctionBeginHot;
53599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5360a433471fSStefano Zampini   if (line < 0) {
5361a433471fSStefano Zampini     *k  = 0;
5362a433471fSStefano Zampini     *Nc = 0;
5363a433471fSStefano Zampini   } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */
53649e8305c2SJed Brown     *k = 1;
53659e8305c2SJed Brown   } else { /* Assume the full interpolated mesh is in the chart; lines in particular */
53669e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
53679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
53689e8305c2SJed Brown     *k = *k / *Nc + 1;
53699e8305c2SJed Brown   }
53709e8305c2SJed Brown   PetscFunctionReturn(0);
53719e8305c2SJed Brown }
53729e8305c2SJed Brown 
5373a4355906SMatthew Knepley /*@
5374bc1eb3faSJed Brown 
5375bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5376bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
53771bb6d2a8SBarry Smith   section provided (or the section of the DM).
5378a4355906SMatthew Knepley 
5379a4355906SMatthew Knepley   Input Parameters:
5380a4355906SMatthew Knepley + dm      - The DM
5381a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5382a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5383a4355906SMatthew Knepley 
5384bc1eb3faSJed Brown   Example:
5385bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5386bc1eb3faSJed Brown .vb
5387bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5388bc1eb3faSJed Brown 
5389bc1eb3faSJed Brown   v4 -- e6 -- v3
5390bc1eb3faSJed Brown   |           |
5391bc1eb3faSJed Brown   e7    c0    e8
5392bc1eb3faSJed Brown   |           |
5393bc1eb3faSJed Brown   v1 -- e5 -- v2
5394bc1eb3faSJed Brown .ve
5395bc1eb3faSJed Brown 
5396bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5397bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5398bc1eb3faSJed Brown .vb
5399bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5400bc1eb3faSJed Brown     v1 -> [4]
5401bc1eb3faSJed Brown     ...
5402bc1eb3faSJed Brown     e5 -> [8, 9]
5403bc1eb3faSJed Brown .ve
5404bc1eb3faSJed Brown 
5405bc1eb3faSJed Brown   which corresponds to the dofs
5406bc1eb3faSJed Brown .vb
5407bc1eb3faSJed Brown     6   10  11  7
5408bc1eb3faSJed Brown     13  2   3   15
5409bc1eb3faSJed Brown     12  0   1   14
5410bc1eb3faSJed Brown     4   8   9   5
5411bc1eb3faSJed Brown .ve
5412bc1eb3faSJed Brown 
5413bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5414bc1eb3faSJed Brown .vb
5415bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5416bc1eb3faSJed Brown .ve
5417bc1eb3faSJed Brown 
5418bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5419bc1eb3faSJed Brown .vb
5420bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5421bc1eb3faSJed Brown .ve
5422bc1eb3faSJed Brown 
5423a4355906SMatthew Knepley   Level: developer
5424a4355906SMatthew Knepley 
5425a1cb98faSBarry Smith   Note:
5426a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5427a1cb98faSBarry Smith   degree of the basis.
5428a1cb98faSBarry Smith 
5429a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5430a4355906SMatthew Knepley @*/
5431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5432d71ae5a4SJacob Faibussowitsch {
54337391a63aSMatthew G. Knepley   DMLabel   label;
5434bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
54359e8305c2SJed Brown   PetscBool vertexchart;
54363194fc30SMatthew G. Knepley 
54373194fc30SMatthew G. Knepley   PetscFunctionBegin;
54389566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5439a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5440a433471fSStefano Zampini   if (point < 0) {
5441a433471fSStefano Zampini     PetscInt sStart, sEnd;
5442a433471fSStefano Zampini 
54439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5444a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5445a433471fSStefano Zampini   }
54469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
54479566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
54489566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
54499371c9d4SSatish Balay   if (depth == 1) {
54509371c9d4SSatish Balay     eStart = point;
54519371c9d4SSatish Balay   } else if (depth == dim) {
54527391a63aSMatthew G. Knepley     const PetscInt *cone;
54537391a63aSMatthew G. Knepley 
54549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5455d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5456d4e6627bSStefano Zampini     else if (dim == 3) {
5457d4e6627bSStefano Zampini       const PetscInt *cone2;
54589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5459d4e6627bSStefano Zampini       eStart = cone2[0];
546063a3b9bcSJacob 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);
546163a3b9bcSJacob 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);
54629e8305c2SJed Brown   { /* Determine whether the chart covers all points or just vertices. */
54639e8305c2SJed Brown     PetscInt pStart, pEnd, cStart, cEnd;
54649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd));
54659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section, &cStart, &cEnd));
5466796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5467796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5468796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
54699e8305c2SJed Brown   }
54709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5471bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5472bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5473bb197d40SJed Brown     PetscInt *perm;
5474bb197d40SJed Brown 
54753194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
54769566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5477bb197d40SJed Brown       size += PetscPowInt(k + 1, d) * Nc;
54783194fc30SMatthew G. Knepley     }
54799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
54803194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5481bb197d40SJed Brown       switch (d) {
5482babf31e0SJed Brown       case 1:
54839566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5484babf31e0SJed Brown         /*
5485babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5486babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5487babf31e0SJed Brown          */
5488babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
54899371c9d4SSatish Balay         for (i = 0; i < k - 1; i++)
54909371c9d4SSatish Balay           for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5491babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5492babf31e0SJed Brown         foffset = offset;
5493babf31e0SJed Brown         break;
549489eabcffSMatthew G. Knepley       case 2:
54953194fc30SMatthew 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} */
54969566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
54973194fc30SMatthew G. Knepley         /* The SEM order is
54983194fc30SMatthew G. Knepley 
54993194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
550089eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
55013194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
55023194fc30SMatthew G. Knepley          */
55033194fc30SMatthew G. Knepley         {
55043194fc30SMatthew G. Knepley           const PetscInt of   = 0;
55053194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
55063194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
55073194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
55083194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
55093194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
55103194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
55113194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
55123194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
55133194fc30SMatthew G. Knepley           PetscInt       o;
55143194fc30SMatthew G. Knepley 
55153194fc30SMatthew G. Knepley           /* bottom */
55163194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
55179371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
55189371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55193194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
55203194fc30SMatthew G. Knepley           /* middle */
55213194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
55223194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
55239371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
55249371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55253194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
55263194fc30SMatthew G. Knepley           }
55273194fc30SMatthew G. Knepley           /* top */
55283194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
55299371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
55309371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
55313194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
55323194fc30SMatthew G. Knepley           foffset = offset;
55333194fc30SMatthew G. Knepley         }
553489eabcffSMatthew G. Knepley         break;
553589eabcffSMatthew G. Knepley       case 3:
553689eabcffSMatthew G. Knepley         /* The original hex closure is
553789eabcffSMatthew G. Knepley 
553889eabcffSMatthew G. Knepley          {c,
553989eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
554089eabcffSMatthew 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,
554189eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
554289eabcffSMatthew G. Knepley          */
55439566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
554489eabcffSMatthew G. Knepley         /* The SEM order is
554589eabcffSMatthew G. Knepley          Bottom Slice
554689eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
554789eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
554889eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
554989eabcffSMatthew G. Knepley 
555089eabcffSMatthew G. Knepley          Middle Slice (j)
555189eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
555289eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
555389eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
555489eabcffSMatthew G. Knepley 
555589eabcffSMatthew G. Knepley          Top Slice
555689eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
555789eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
555889eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
555989eabcffSMatthew G. Knepley          */
556089eabcffSMatthew G. Knepley         {
556189eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
556289eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
556389eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
556489eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
556589eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
556689eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
556789eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
556889eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
556989eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
557089eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
557189eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
557289eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
557389eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
557489eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
557589eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
557689eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
557789eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
557889eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
557989eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
558089eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
558189eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
558289eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
558389eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
558489eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
558589eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
558689eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
558789eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
558889eabcffSMatthew G. Knepley           PetscInt       o, n;
558989eabcffSMatthew G. Knepley 
559089eabcffSMatthew G. Knepley           /* Bottom Slice */
559189eabcffSMatthew G. Knepley           /*   bottom */
559289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
55939371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
55949371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
559589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
559689eabcffSMatthew G. Knepley           /*   middle */
559789eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
559889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
55999371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
56009371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
56019371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56029371c9d4SSatish Balay             }
560389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
56043194fc30SMatthew G. Knepley           }
560589eabcffSMatthew G. Knepley           /*   top */
560689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
56079371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
56089371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
560989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
561089eabcffSMatthew G. Knepley 
561189eabcffSMatthew G. Knepley           /* Middle Slice */
561289eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
561389eabcffSMatthew G. Knepley             /*   bottom */
561489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
56159371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
56169371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
561789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
561889eabcffSMatthew G. Knepley             /*   middle */
561989eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
562089eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
56219371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
56229371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
562389eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
562489eabcffSMatthew G. Knepley             }
562589eabcffSMatthew G. Knepley             /*   top */
562689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
56279371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
56289371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
562989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
563089eabcffSMatthew G. Knepley           }
563189eabcffSMatthew G. Knepley 
563289eabcffSMatthew G. Knepley           /* Top Slice */
563389eabcffSMatthew G. Knepley           /*   bottom */
563489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
56359371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
56369371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
563789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
563889eabcffSMatthew G. Knepley           /*   middle */
563989eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
564089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
56419371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
56429371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
564389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
564489eabcffSMatthew G. Knepley           }
564589eabcffSMatthew G. Knepley           /*   top */
564689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
56479371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
56489371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
564989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
565089eabcffSMatthew G. Knepley 
565189eabcffSMatthew G. Knepley           foffset = offset;
565289eabcffSMatthew G. Knepley         }
565389eabcffSMatthew G. Knepley         break;
5654d71ae5a4SJacob Faibussowitsch       default:
5655d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
565689eabcffSMatthew G. Knepley       }
565789eabcffSMatthew G. Knepley     }
565863a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
56593194fc30SMatthew G. Knepley     /* Check permutation */
56603194fc30SMatthew G. Knepley     {
56613194fc30SMatthew G. Knepley       PetscInt *check;
56623194fc30SMatthew G. Knepley 
56639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
56641dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
56651dca8a05SBarry Smith         check[i] = -1;
56661dca8a05SBarry 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]);
56671dca8a05SBarry Smith       }
56683194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
56691dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
56709566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
56713194fc30SMatthew G. Knepley     }
56729566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
5673a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5674a05c9aa3SJed Brown       PetscInt *loc_perm;
56759566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
5676a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
5677a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
5678a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
5679a05c9aa3SJed Brown       }
56809566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
5681a05c9aa3SJed Brown     }
5682bb197d40SJed Brown   }
56833194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
56843194fc30SMatthew G. Knepley }
56853194fc30SMatthew G. Knepley 
5686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5687d71ae5a4SJacob Faibussowitsch {
5688e071409bSToby Isaac   PetscDS  prob;
5689e071409bSToby Isaac   PetscInt depth, Nf, h;
5690e071409bSToby Isaac   DMLabel  label;
5691e071409bSToby Isaac 
5692e071409bSToby Isaac   PetscFunctionBeginHot;
56939566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5694e071409bSToby Isaac   Nf      = prob->Nf;
5695e071409bSToby Isaac   label   = dm->depthLabel;
5696e071409bSToby Isaac   *dspace = NULL;
5697e071409bSToby Isaac   if (field < Nf) {
5698e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5699e071409bSToby Isaac 
5700e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5701e071409bSToby Isaac       PetscDualSpace dsp;
5702e071409bSToby Isaac 
57039566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
57049566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
57059566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
5706e071409bSToby Isaac       h = depth - 1 - h;
5707e071409bSToby Isaac       if (h) {
57089566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
5709e071409bSToby Isaac       } else {
5710e071409bSToby Isaac         *dspace = dsp;
5711e071409bSToby Isaac       }
5712e071409bSToby Isaac     }
5713e071409bSToby Isaac   }
5714e071409bSToby Isaac   PetscFunctionReturn(0);
5715e071409bSToby Isaac }
5716e071409bSToby Isaac 
5717d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5718d71ae5a4SJacob Faibussowitsch {
571928351e22SJed Brown   PetscScalar       *array;
572028351e22SJed Brown   const PetscScalar *vArray;
5721d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
57221a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
5723552f7358SJed Brown 
57241b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
57259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
57269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
57279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
57289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
57293f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
57309df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
57319df71ca4SMatthew G. Knepley       PetscInt dof;
5732d9917b9dSMatthew G. Knepley 
57339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
57349df71ca4SMatthew G. Knepley       size += dof;
57359df71ca4SMatthew G. Knepley     }
57369df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
57379df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
57382a3aaacfSMatthew G. Knepley       PetscInt       dof;
57395a1bb5cfSMatthew G. Knepley 
57405a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
57419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
57425a1bb5cfSMatthew G. Knepley       size += dof;
57435a1bb5cfSMatthew G. Knepley     }
57443f7cbbe7SMatthew G. Knepley     if (!values) {
57453f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
57463f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
57473f7cbbe7SMatthew G. Knepley     }
57489566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5749982e9ed1SMatthew G. Knepley   } else {
5750982e9ed1SMatthew G. Knepley     array = *values;
5751982e9ed1SMatthew G. Knepley   }
57529df71ca4SMatthew G. Knepley   size = 0;
575328351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
57549df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
57559df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
575628351e22SJed Brown     const PetscScalar *varr;
5757d9917b9dSMatthew G. Knepley 
57589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
57599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
57609df71ca4SMatthew G. Knepley     varr = &vArray[off];
5761ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
57629df71ca4SMatthew G. Knepley     size += dof;
57639df71ca4SMatthew G. Knepley   }
57649df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
57659df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
57669df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
57675a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
576828351e22SJed Brown     const PetscScalar *varr;
57695a1bb5cfSMatthew G. Knepley 
577052ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
57719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
57729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
57735a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
57745a1bb5cfSMatthew G. Knepley     if (o >= 0) {
5775ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
57765a1bb5cfSMatthew G. Knepley     } else {
5777ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
57785a1bb5cfSMatthew G. Knepley     }
57799df71ca4SMatthew G. Knepley     size += dof;
57805a1bb5cfSMatthew G. Knepley   }
578128351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
57829df71ca4SMatthew G. Knepley   if (!*values) {
57835a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
57845a1bb5cfSMatthew G. Knepley     *values = array;
57859df71ca4SMatthew G. Knepley   } else {
578663a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
57878c312ff3SMatthew G. Knepley     *csize = size;
57889df71ca4SMatthew G. Knepley   }
57895a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
57905a1bb5cfSMatthew G. Knepley }
5791d9917b9dSMatthew G. Knepley 
579227f02ce8SMatthew G. Knepley /* Compress out points not in the section */
5793d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
5794d71ae5a4SJacob Faibussowitsch {
579527f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
579627f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
579727f02ce8SMatthew G. Knepley 
57989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
579927f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
580027f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
580127f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
580227f02ce8SMatthew G. Knepley       points[q * 2]     = r;
580327f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
580427f02ce8SMatthew G. Knepley       ++q;
580527f02ce8SMatthew G. Knepley     }
580627f02ce8SMatthew G. Knepley   }
580727f02ce8SMatthew G. Knepley   *numPoints = q;
580827f02ce8SMatthew G. Knepley   return 0;
580927f02ce8SMatthew G. Knepley }
581027f02ce8SMatthew G. Knepley 
581197529cf3SJed Brown /* Compressed closure does not apply closure permutation */
5812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5813d71ae5a4SJacob Faibussowitsch {
581427f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5815923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
5816923c78e0SToby Isaac 
5817923c78e0SToby Isaac   PetscFunctionBeginHot;
58189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
581927f02ce8SMatthew G. Knepley   if (*clPoints) {
5820923c78e0SToby Isaac     PetscInt dof, off;
5821923c78e0SToby Isaac 
58229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
58239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
58249566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5825923c78e0SToby Isaac     np  = dof / 2;
5826923c78e0SToby Isaac     pts = (PetscInt *)&cla[off];
582727f02ce8SMatthew G. Knepley   } else {
58289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
58299566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5830923c78e0SToby Isaac   }
5831923c78e0SToby Isaac   *numPoints = np;
5832923c78e0SToby Isaac   *points    = pts;
5833923c78e0SToby Isaac   *clp       = cla;
5834923c78e0SToby Isaac   PetscFunctionReturn(0);
5835923c78e0SToby Isaac }
5836923c78e0SToby Isaac 
5837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5838d71ae5a4SJacob Faibussowitsch {
5839923c78e0SToby Isaac   PetscFunctionBeginHot;
5840923c78e0SToby Isaac   if (!*clPoints) {
58419566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5842923c78e0SToby Isaac   } else {
58439566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5844923c78e0SToby Isaac   }
5845923c78e0SToby Isaac   *numPoints = 0;
5846923c78e0SToby Isaac   *points    = NULL;
5847923c78e0SToby Isaac   *clSec     = NULL;
5848923c78e0SToby Isaac   *clPoints  = NULL;
5849923c78e0SToby Isaac   *clp       = NULL;
5850923c78e0SToby Isaac   PetscFunctionReturn(0);
5851923c78e0SToby Isaac }
5852923c78e0SToby Isaac 
5853d71ae5a4SJacob 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[])
5854d71ae5a4SJacob Faibussowitsch {
58551a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
585697e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
585797e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
58581a271a75SMatthew G. Knepley 
58591a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5860fe02ba77SJed Brown   *size = 0;
58619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
586297e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
586397e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
586497e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
586597e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
58661a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
58671a271a75SMatthew G. Knepley     const PetscScalar *varr;
58681a271a75SMatthew G. Knepley 
58699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
58709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
58711a271a75SMatthew G. Knepley     varr = &vArray[off];
587297e99dd9SToby Isaac     if (clperm) {
587397e99dd9SToby Isaac       if (perm) {
587497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
58751a271a75SMatthew G. Knepley       } else {
587697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
587797e99dd9SToby Isaac       }
587897e99dd9SToby Isaac       if (flip) {
587997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
588097e99dd9SToby Isaac       }
588197e99dd9SToby Isaac     } else {
588297e99dd9SToby Isaac       if (perm) {
588397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
588497e99dd9SToby Isaac       } else {
588597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
588697e99dd9SToby Isaac       }
588797e99dd9SToby Isaac       if (flip) {
588897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
58891a271a75SMatthew G. Knepley       }
58901a271a75SMatthew G. Knepley     }
589197e99dd9SToby Isaac     offset += dof;
589297e99dd9SToby Isaac   }
58939566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
58941a271a75SMatthew G. Knepley   *size = offset;
58951a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
58961a271a75SMatthew G. Knepley }
58971a271a75SMatthew G. Knepley 
5898d71ae5a4SJacob 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[])
5899d71ae5a4SJacob Faibussowitsch {
59001a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
59011a271a75SMatthew G. Knepley 
59021a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5903fe02ba77SJed Brown   *size = 0;
59041a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
590597e99dd9SToby Isaac     PetscInt            p;
590697e99dd9SToby Isaac     const PetscInt    **perms = NULL;
590797e99dd9SToby Isaac     const PetscScalar **flips = NULL;
59081a271a75SMatthew G. Knepley 
59099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
591097e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
591197e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
591297e99dd9SToby Isaac       PetscInt           fdof, foff, b;
59131a271a75SMatthew G. Knepley       const PetscScalar *varr;
591497e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
591597e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
59161a271a75SMatthew G. Knepley 
59179566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
59189566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
59191a271a75SMatthew G. Knepley       varr = &vArray[foff];
592097e99dd9SToby Isaac       if (clperm) {
59219371c9d4SSatish Balay         if (perm) {
5922ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
59231a271a75SMatthew G. Knepley         } else {
5924ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
59259371c9d4SSatish Balay         }
59269371c9d4SSatish Balay         if (flip) {
5927ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
59289371c9d4SSatish Balay         }
59299371c9d4SSatish Balay       } else {
59309371c9d4SSatish Balay         if (perm) {
5931ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
59329371c9d4SSatish Balay         } else {
5933ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
59349371c9d4SSatish Balay         }
59359371c9d4SSatish Balay         if (flip) {
5936ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
59379371c9d4SSatish Balay         }
59381a271a75SMatthew G. Knepley       }
593997e99dd9SToby Isaac       offset += fdof;
59401a271a75SMatthew G. Knepley     }
59419566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
59421a271a75SMatthew G. Knepley   }
59431a271a75SMatthew G. Knepley   *size = offset;
59441a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
59451a271a75SMatthew G. Knepley }
59461a271a75SMatthew G. Knepley 
5947552f7358SJed Brown /*@C
5948552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5949552f7358SJed Brown 
5950552f7358SJed Brown   Not collective
5951552f7358SJed Brown 
5952552f7358SJed Brown   Input Parameters:
5953a1cb98faSBarry Smith + dm - The `DM`
5954552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5955552f7358SJed Brown . v - The local vector
5956a1cb98faSBarry Smith - point - The point in the `DM`
5957552f7358SJed Brown 
59586b867d5aSJose E. Roman   Input/Output Parameters:
59596b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
59606b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
59616b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
596222c1ee49SMatthew G. Knepley 
5963552f7358SJed Brown   Level: intermediate
5964552f7358SJed Brown 
5965a1cb98faSBarry Smith   Notes:
5966a1cb98faSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to NULL in the
5967a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
5968a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
5969a1cb98faSBarry Smith 
5970a1cb98faSBarry Smith   A typical use could be
5971a1cb98faSBarry Smith .vb
5972a1cb98faSBarry Smith    values = NULL;
5973a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
5974a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
5975a1cb98faSBarry Smith      <Compute on closure>
5976a1cb98faSBarry Smith    }
5977a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
5978a1cb98faSBarry Smith .ve
5979a1cb98faSBarry Smith   or
5980a1cb98faSBarry Smith .vb
5981a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
5982a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
5983a1cb98faSBarry Smith      clSize = clMaxSize;
5984a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
5985a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
5986a1cb98faSBarry Smith        <Compute on closure>
5987a1cb98faSBarry Smith      }
5988a1cb98faSBarry Smith    }
5989a1cb98faSBarry Smith    PetscFree(values);
5990a1cb98faSBarry Smith .ve
5991a1cb98faSBarry Smith 
5992a1cb98faSBarry Smith   Fortran Note:
5993a1cb98faSBarry Smith   The csize argument is not present in the Fortran binding since it is internal to the array.
5994a1cb98faSBarry Smith 
5995a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5996552f7358SJed Brown @*/
5997d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5998d71ae5a4SJacob Faibussowitsch {
5999552f7358SJed Brown   PetscSection    clSection;
6000d9917b9dSMatthew G. Knepley   IS              clPoints;
6001552f7358SJed Brown   PetscInt       *points = NULL;
6002c459fbc1SJed Brown   const PetscInt *clp, *perm;
6003c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, asize;
6004552f7358SJed Brown 
6005d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
6006552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
60079566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
60081a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
60091a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
60109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
60119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6012552f7358SJed Brown   if (depth == 1 && numFields < 2) {
60139566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
6014552f7358SJed Brown     PetscFunctionReturn(0);
6015552f7358SJed Brown   }
60161a271a75SMatthew G. Knepley   /* Get points */
60179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6018c459fbc1SJed Brown   /* Get sizes */
6019c459fbc1SJed Brown   asize = 0;
6020c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
6021c459fbc1SJed Brown     PetscInt dof;
60229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
60231a271a75SMatthew G. Knepley     asize += dof;
6024552f7358SJed Brown   }
6025c459fbc1SJed Brown   if (values) {
6026c459fbc1SJed Brown     const PetscScalar *vArray;
6027c459fbc1SJed Brown     PetscInt           size;
6028c459fbc1SJed Brown 
6029c459fbc1SJed Brown     if (*values) {
603063a3b9bcSJacob Faibussowitsch       PetscCheck(*csize >= asize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %" PetscInt_FMT " not sufficient to hold closure size %" PetscInt_FMT, *csize, asize);
60319566063dSJacob Faibussowitsch     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
60329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
60339566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v, &vArray));
60341a271a75SMatthew G. Knepley     /* Get values */
60359566063dSJacob Faibussowitsch     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
60369566063dSJacob Faibussowitsch     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
603763a3b9bcSJacob Faibussowitsch     PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
60381a271a75SMatthew G. Knepley     /* Cleanup array */
60399566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v, &vArray));
6040d0f6b257SMatthew G. Knepley   }
6041c459fbc1SJed Brown   if (csize) *csize = asize;
6042c459fbc1SJed Brown   /* Cleanup points */
60439566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6044552f7358SJed Brown   PetscFunctionReturn(0);
6045552f7358SJed Brown }
6046552f7358SJed Brown 
6047d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6048d71ae5a4SJacob Faibussowitsch {
6049e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6050e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6051e5c487bfSMatthew G. Knepley   IS                 clPoints;
6052e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6053e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6054e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6055c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6056c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6057e5c487bfSMatthew G. Knepley 
6058e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6059e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
60609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6061e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6062e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
60639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
60649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
60659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6066e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
60679566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
6068e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
6069e5c487bfSMatthew G. Knepley   }
6070e5c487bfSMatthew G. Knepley   /* Get points */
60719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6072c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6073c459fbc1SJed Brown     PetscInt dof;
60749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6075c459fbc1SJed Brown     clsize += dof;
6076c459fbc1SJed Brown   }
60779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6078e5c487bfSMatthew G. Knepley   /* Filter points */
6079e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6080e5c487bfSMatthew G. Knepley     PetscInt dep;
6081e5c487bfSMatthew G. Knepley 
60829566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6083e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6084e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6085e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6086e5c487bfSMatthew G. Knepley     ++Np;
6087e5c487bfSMatthew G. Knepley   }
6088e5c487bfSMatthew G. Knepley   /* Get array */
6089e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6090e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6091e5c487bfSMatthew G. Knepley 
6092e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
60939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6094e5c487bfSMatthew G. Knepley       asize += dof;
6095e5c487bfSMatthew G. Knepley     }
6096e5c487bfSMatthew G. Knepley     if (!values) {
60979566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6098e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
6099e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
6100e5c487bfSMatthew G. Knepley     }
61019566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6102e5c487bfSMatthew G. Knepley   } else {
6103e5c487bfSMatthew G. Knepley     array = *values;
6104e5c487bfSMatthew G. Knepley   }
61059566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6106e5c487bfSMatthew G. Knepley   /* Get values */
61079566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
61089566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6109e5c487bfSMatthew G. Knepley   /* Cleanup points */
61109566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6111e5c487bfSMatthew G. Knepley   /* Cleanup array */
61129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6113e5c487bfSMatthew G. Knepley   if (!*values) {
6114e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6115e5c487bfSMatthew G. Knepley     *values = array;
6116e5c487bfSMatthew G. Knepley   } else {
611763a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6118e5c487bfSMatthew G. Knepley     *csize = size;
6119e5c487bfSMatthew G. Knepley   }
6120e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
6121e5c487bfSMatthew G. Knepley }
6122e5c487bfSMatthew G. Knepley 
6123552f7358SJed Brown /*@C
6124552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6125552f7358SJed Brown 
6126552f7358SJed Brown   Not collective
6127552f7358SJed Brown 
6128552f7358SJed Brown   Input Parameters:
6129a1cb98faSBarry Smith + dm - The `DM`
61300298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
6131552f7358SJed Brown . v - The local vector
6132a1cb98faSBarry Smith . point - The point in the `DM`
61330298fd71SBarry Smith . csize - The number of values in the closure, or NULL
6134552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
6135552f7358SJed Brown 
6136552f7358SJed Brown   Level: intermediate
6137552f7358SJed Brown 
6138a1cb98faSBarry Smith   Note:
6139a1cb98faSBarry Smith   The array values are discarded and not copied back into v. In order to copy values back to v, use `DMPlexVecSetClosure()`
6140a1cb98faSBarry Smith 
6141a1cb98faSBarry Smith   Fortran Note:
6142a1cb98faSBarry Smith   The csize argument is not present in the Fortran binding since it is internal to the array.
6143a1cb98faSBarry Smith 
6144a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6145552f7358SJed Brown @*/
6146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6147d71ae5a4SJacob Faibussowitsch {
6148552f7358SJed Brown   PetscInt size = 0;
6149552f7358SJed Brown 
6150552f7358SJed Brown   PetscFunctionBegin;
6151552f7358SJed Brown   /* Should work without recalculating size */
61529566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6153c9fdaa05SMatthew G. Knepley   *values = NULL;
6154552f7358SJed Brown   PetscFunctionReturn(0);
6155552f7358SJed Brown }
6156552f7358SJed Brown 
6157d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6158d71ae5a4SJacob Faibussowitsch {
61599371c9d4SSatish Balay   *x += y;
61609371c9d4SSatish Balay }
6161d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6162d71ae5a4SJacob Faibussowitsch {
61639371c9d4SSatish Balay   *x = y;
61649371c9d4SSatish Balay }
6165552f7358SJed Brown 
6166d71ae5a4SJacob 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[])
6167d71ae5a4SJacob Faibussowitsch {
6168552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6169552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6170552f7358SJed Brown   PetscScalar    *a;
6171552f7358SJed Brown   PetscInt        off, cind = 0, k;
6172552f7358SJed Brown 
6173552f7358SJed Brown   PetscFunctionBegin;
61749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
61759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6176552f7358SJed Brown   a = &array[off];
6177552f7358SJed Brown   if (!cdof || setBC) {
617897e99dd9SToby Isaac     if (clperm) {
61799371c9d4SSatish Balay       if (perm) {
6180ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6181552f7358SJed Brown       } else {
6182ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
61839371c9d4SSatish Balay       }
61849371c9d4SSatish Balay     } else {
61859371c9d4SSatish Balay       if (perm) {
6186ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
61879371c9d4SSatish Balay       } else {
6188ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
61899371c9d4SSatish Balay       }
6190552f7358SJed Brown     }
6191552f7358SJed Brown   } else {
61929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
619397e99dd9SToby Isaac     if (clperm) {
61949371c9d4SSatish Balay       if (perm) {
61959371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
61969371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
61979371c9d4SSatish Balay             ++cind;
61989371c9d4SSatish Balay             continue;
61999371c9d4SSatish Balay           }
620097e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6201552f7358SJed Brown         }
6202552f7358SJed Brown       } else {
6203552f7358SJed Brown         for (k = 0; k < dof; ++k) {
62049371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62059371c9d4SSatish Balay             ++cind;
62069371c9d4SSatish Balay             continue;
62079371c9d4SSatish Balay           }
620897e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
620997e99dd9SToby Isaac         }
621097e99dd9SToby Isaac       }
621197e99dd9SToby Isaac     } else {
621297e99dd9SToby Isaac       if (perm) {
621397e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
62149371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62159371c9d4SSatish Balay             ++cind;
62169371c9d4SSatish Balay             continue;
62179371c9d4SSatish Balay           }
621897e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
621997e99dd9SToby Isaac         }
622097e99dd9SToby Isaac       } else {
622197e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
62229371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62239371c9d4SSatish Balay             ++cind;
62249371c9d4SSatish Balay             continue;
62259371c9d4SSatish Balay           }
622697e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
622797e99dd9SToby Isaac         }
6228552f7358SJed Brown       }
6229552f7358SJed Brown     }
6230552f7358SJed Brown   }
6231552f7358SJed Brown   PetscFunctionReturn(0);
6232552f7358SJed Brown }
6233552f7358SJed Brown 
6234d71ae5a4SJacob 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[])
6235d71ae5a4SJacob Faibussowitsch {
6236a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6237a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6238a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6239a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6240a5e93ea8SMatthew G. Knepley 
6241a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
62429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
62439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6244a5e93ea8SMatthew G. Knepley   a = &array[off];
6245a5e93ea8SMatthew G. Knepley   if (cdof) {
62469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
624797e99dd9SToby Isaac     if (clperm) {
624897e99dd9SToby Isaac       if (perm) {
6249a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6250a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
625197e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
625297e99dd9SToby Isaac             cind++;
6253a5e93ea8SMatthew G. Knepley           }
6254a5e93ea8SMatthew G. Knepley         }
6255a5e93ea8SMatthew G. Knepley       } else {
6256a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6257a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
625897e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
625997e99dd9SToby Isaac             cind++;
626097e99dd9SToby Isaac           }
626197e99dd9SToby Isaac         }
626297e99dd9SToby Isaac       }
626397e99dd9SToby Isaac     } else {
626497e99dd9SToby Isaac       if (perm) {
626597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
626697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
626797e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
626897e99dd9SToby Isaac             cind++;
626997e99dd9SToby Isaac           }
627097e99dd9SToby Isaac         }
627197e99dd9SToby Isaac       } else {
627297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
627397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
627497e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
627597e99dd9SToby Isaac             cind++;
627697e99dd9SToby Isaac           }
6277a5e93ea8SMatthew G. Knepley         }
6278a5e93ea8SMatthew G. Knepley       }
6279a5e93ea8SMatthew G. Knepley     }
6280a5e93ea8SMatthew G. Knepley   }
6281a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6282a5e93ea8SMatthew G. Knepley }
6283a5e93ea8SMatthew G. Knepley 
6284d71ae5a4SJacob 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[])
6285d71ae5a4SJacob Faibussowitsch {
6286552f7358SJed Brown   PetscScalar    *a;
62871a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
62881a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
628997e99dd9SToby Isaac   PetscInt        cind = 0, b;
6290552f7358SJed Brown 
6291552f7358SJed Brown   PetscFunctionBegin;
62929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
62939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
62949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
62951a271a75SMatthew G. Knepley   a = &array[foff];
6296552f7358SJed Brown   if (!fcdof || setBC) {
629797e99dd9SToby Isaac     if (clperm) {
62989371c9d4SSatish Balay       if (perm) {
6299ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6300552f7358SJed Brown       } else {
6301ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
63029371c9d4SSatish Balay       }
63039371c9d4SSatish Balay     } else {
63049371c9d4SSatish Balay       if (perm) {
6305ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
63069371c9d4SSatish Balay       } else {
6307ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
63089371c9d4SSatish Balay       }
6309552f7358SJed Brown     }
6310552f7358SJed Brown   } else {
63119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
631297e99dd9SToby Isaac     if (clperm) {
631397e99dd9SToby Isaac       if (perm) {
631497e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63159371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63169371c9d4SSatish Balay             ++cind;
63179371c9d4SSatish Balay             continue;
63189371c9d4SSatish Balay           }
631997e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6320552f7358SJed Brown         }
6321552f7358SJed Brown       } else {
632297e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63239371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63249371c9d4SSatish Balay             ++cind;
63259371c9d4SSatish Balay             continue;
63269371c9d4SSatish Balay           }
632797e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
632897e99dd9SToby Isaac         }
632997e99dd9SToby Isaac       }
633097e99dd9SToby Isaac     } else {
633197e99dd9SToby Isaac       if (perm) {
633297e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63339371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63349371c9d4SSatish Balay             ++cind;
63359371c9d4SSatish Balay             continue;
63369371c9d4SSatish Balay           }
633797e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
633897e99dd9SToby Isaac         }
633997e99dd9SToby Isaac       } else {
634097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
63419371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
63429371c9d4SSatish Balay             ++cind;
63439371c9d4SSatish Balay             continue;
63449371c9d4SSatish Balay           }
634597e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6346552f7358SJed Brown         }
6347552f7358SJed Brown       }
6348552f7358SJed Brown     }
6349552f7358SJed Brown   }
63501a271a75SMatthew G. Knepley   *offset += fdof;
6351552f7358SJed Brown   PetscFunctionReturn(0);
6352552f7358SJed Brown }
6353552f7358SJed Brown 
6354d71ae5a4SJacob 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[])
6355d71ae5a4SJacob Faibussowitsch {
6356a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
63571a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
63581a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
63595da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6360ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6361a5e93ea8SMatthew G. Knepley 
6362a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
63639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
63649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
63669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63671a271a75SMatthew G. Knepley   a = &array[foff];
6368a5e93ea8SMatthew G. Knepley   if (fcdof) {
6369ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
63709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
637197e99dd9SToby Isaac     if (clperm) {
637297e99dd9SToby Isaac       if (perm) {
6373ba322698SMatthew G. Knepley         if (comps) {
6374ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6375ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
63769371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
63779371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
63789371c9d4SSatish Balay               ncSet = PETSC_TRUE;
63799371c9d4SSatish Balay             }
63809371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
63819371c9d4SSatish Balay               ++cind;
63829371c9d4SSatish Balay               fcSet = PETSC_TRUE;
63839371c9d4SSatish Balay             }
6384ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6385ba322698SMatthew G. Knepley           }
6386ba322698SMatthew G. Knepley         } else {
638797e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
638897e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
638997e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6390a5e93ea8SMatthew G. Knepley               ++cind;
6391a5e93ea8SMatthew G. Knepley             }
6392a5e93ea8SMatthew G. Knepley           }
6393ba322698SMatthew G. Knepley         }
6394ba322698SMatthew G. Knepley       } else {
6395ba322698SMatthew G. Knepley         if (comps) {
6396ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6397ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
63989371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
63999371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64009371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64019371c9d4SSatish Balay             }
64029371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64039371c9d4SSatish Balay               ++cind;
64049371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64059371c9d4SSatish Balay             }
6406ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6407ba322698SMatthew G. Knepley           }
6408a5e93ea8SMatthew G. Knepley         } else {
640997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
641097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
641197e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
641297e99dd9SToby Isaac               ++cind;
641397e99dd9SToby Isaac             }
641497e99dd9SToby Isaac           }
641597e99dd9SToby Isaac         }
6416ba322698SMatthew G. Knepley       }
641797e99dd9SToby Isaac     } else {
641897e99dd9SToby Isaac       if (perm) {
6419ba322698SMatthew G. Knepley         if (comps) {
6420ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6421ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64229371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64239371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64249371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64259371c9d4SSatish Balay             }
64269371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64279371c9d4SSatish Balay               ++cind;
64289371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64299371c9d4SSatish Balay             }
6430ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6431ba322698SMatthew G. Knepley           }
6432ba322698SMatthew G. Knepley         } else {
643397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
643497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
643597e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
643697e99dd9SToby Isaac               ++cind;
643797e99dd9SToby Isaac             }
643897e99dd9SToby Isaac           }
6439ba322698SMatthew G. Knepley         }
6440ba322698SMatthew G. Knepley       } else {
6441ba322698SMatthew G. Knepley         if (comps) {
6442ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6443ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64449371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64459371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64469371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64479371c9d4SSatish Balay             }
64489371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64499371c9d4SSatish Balay               ++cind;
64509371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64519371c9d4SSatish Balay             }
6452ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6453ba322698SMatthew G. Knepley           }
645497e99dd9SToby Isaac         } else {
645597e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
645697e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
645797e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6458a5e93ea8SMatthew G. Knepley               ++cind;
6459a5e93ea8SMatthew G. Knepley             }
6460a5e93ea8SMatthew G. Knepley           }
6461a5e93ea8SMatthew G. Knepley         }
6462a5e93ea8SMatthew G. Knepley       }
6463a5e93ea8SMatthew G. Knepley     }
6464ba322698SMatthew G. Knepley   }
64651a271a75SMatthew G. Knepley   *offset += fdof;
6466a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6467a5e93ea8SMatthew G. Knepley }
6468a5e93ea8SMatthew G. Knepley 
6469d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6470d71ae5a4SJacob Faibussowitsch {
6471552f7358SJed Brown   PetscScalar    *array;
64721b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
64731b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6474552f7358SJed Brown 
64751b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
64769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
64779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
64789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
64799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
64809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6481b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6482b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6483b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6484b6ebb6e6SMatthew G. Knepley 
64859371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
64869371c9d4SSatish Balay       dof = 0;
64879371c9d4SSatish Balay       continue;
64889371c9d4SSatish Balay     }
64899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6490b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6491b6ebb6e6SMatthew G. Knepley     {
6492b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6493b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6494b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6495b6ebb6e6SMatthew G. Knepley 
64969566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
64979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6498b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6499b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6500b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6501ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6502b6ebb6e6SMatthew G. Knepley         } else {
6503ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6504b6ebb6e6SMatthew G. Knepley         }
6505b6ebb6e6SMatthew G. Knepley       } else {
65069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6507b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6508b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
65099371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
65109371c9d4SSatish Balay               ++cind;
65119371c9d4SSatish Balay               continue;
65129371c9d4SSatish Balay             }
6513b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6514b6ebb6e6SMatthew G. Knepley           }
6515b6ebb6e6SMatthew G. Knepley         } else {
6516b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
65179371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
65189371c9d4SSatish Balay               ++cind;
65199371c9d4SSatish Balay               continue;
65209371c9d4SSatish Balay             }
6521b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6522b6ebb6e6SMatthew G. Knepley           }
6523b6ebb6e6SMatthew G. Knepley         }
6524b6ebb6e6SMatthew G. Knepley       }
6525b6ebb6e6SMatthew G. Knepley     }
6526b6ebb6e6SMatthew G. Knepley   }
65279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6528b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6529b6ebb6e6SMatthew G. Knepley }
65301b406b76SMatthew G. Knepley 
65311b406b76SMatthew G. Knepley /*@C
65321b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
65331b406b76SMatthew G. Knepley 
65341b406b76SMatthew G. Knepley   Not collective
65351b406b76SMatthew G. Knepley 
65361b406b76SMatthew G. Knepley   Input Parameters:
6537a1cb98faSBarry Smith + dm - The `DM`
65381b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
65391b406b76SMatthew G. Knepley . v - The local vector
6540eaf898f9SPatrick Sanan . point - The point in the DM
65411b406b76SMatthew G. Knepley . values - The array of values
6542a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6543a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
65441b406b76SMatthew G. Knepley 
65451b406b76SMatthew G. Knepley   Level: intermediate
65461b406b76SMatthew G. Knepley 
6547a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
65481b406b76SMatthew G. Knepley @*/
6549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6550d71ae5a4SJacob Faibussowitsch {
65511b406b76SMatthew G. Knepley   PetscSection    clSection;
65521b406b76SMatthew G. Knepley   IS              clPoints;
65531b406b76SMatthew G. Knepley   PetscScalar    *array;
65541b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
655527f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6556c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
65571b406b76SMatthew G. Knepley 
65581a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
65591b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
65611a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
65621a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
65639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
65649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
65651b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
65669566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
65671b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
65681b406b76SMatthew G. Knepley   }
65691a271a75SMatthew G. Knepley   /* Get points */
65709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6571c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6572c459fbc1SJed Brown     PetscInt dof;
65739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6574c459fbc1SJed Brown     clsize += dof;
6575c459fbc1SJed Brown   }
65769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
65771a271a75SMatthew G. Knepley   /* Get array */
65789566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
65791a271a75SMatthew G. Knepley   /* Get values */
6580ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
658197e99dd9SToby Isaac     PetscInt offset = 0, f;
6582552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
658397e99dd9SToby Isaac       const PetscInt    **perms = NULL;
658497e99dd9SToby Isaac       const PetscScalar **flips = NULL;
658597e99dd9SToby Isaac 
65869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6587552f7358SJed Brown       switch (mode) {
6588552f7358SJed Brown       case INSERT_VALUES:
658997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
659097e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
659197e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
659297e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
659397e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
65949371c9d4SSatish Balay         }
65959371c9d4SSatish Balay         break;
6596552f7358SJed Brown       case INSERT_ALL_VALUES:
659797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
659897e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
659997e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
660097e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
660197e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
66029371c9d4SSatish Balay         }
66039371c9d4SSatish Balay         break;
6604a5e93ea8SMatthew G. Knepley       case INSERT_BC_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;
6609ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
66109371c9d4SSatish Balay         }
66119371c9d4SSatish Balay         break;
6612552f7358SJed Brown       case ADD_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;
661797e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
66189371c9d4SSatish Balay         }
66199371c9d4SSatish Balay         break;
6620552f7358SJed Brown       case ADD_ALL_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;
662597e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
66269371c9d4SSatish Balay         }
66279371c9d4SSatish Balay         break;
6628304ab55fSMatthew G. Knepley       case ADD_BC_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;
6633ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
66349371c9d4SSatish Balay         }
66359371c9d4SSatish Balay         break;
6636d71ae5a4SJacob Faibussowitsch       default:
6637d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6638552f7358SJed Brown       }
66399566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
66401a271a75SMatthew G. Knepley     }
6641552f7358SJed Brown   } else {
66421a271a75SMatthew G. Knepley     PetscInt            dof, off;
664397e99dd9SToby Isaac     const PetscInt    **perms = NULL;
664497e99dd9SToby Isaac     const PetscScalar **flips = NULL;
66451a271a75SMatthew G. Knepley 
66469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
6647552f7358SJed Brown     switch (mode) {
6648552f7358SJed Brown     case INSERT_VALUES:
664997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
665097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
665197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
665297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66539566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
665497e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
66559371c9d4SSatish Balay       }
66569371c9d4SSatish Balay       break;
6657552f7358SJed Brown     case INSERT_ALL_VALUES:
665897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
665997e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
666097e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
666197e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
666397e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array);
66649371c9d4SSatish Balay       }
66659371c9d4SSatish Balay       break;
6666a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
666797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
666897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
666997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
667097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
667297e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array);
66739371c9d4SSatish Balay       }
66749371c9d4SSatish Balay       break;
6675552f7358SJed Brown     case ADD_VALUES:
667697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
667797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
667897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
667997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
668197e99dd9SToby Isaac         updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array);
66829371c9d4SSatish Balay       }
66839371c9d4SSatish Balay       break;
6684552f7358SJed Brown     case ADD_ALL_VALUES:
668597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
668697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
668797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
668897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
669097e99dd9SToby Isaac         updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array);
66919371c9d4SSatish Balay       }
66929371c9d4SSatish Balay       break;
6693304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
669497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
669597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
669697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
669797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
66989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
669997e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array);
67009371c9d4SSatish Balay       }
67019371c9d4SSatish Balay       break;
6702d71ae5a4SJacob Faibussowitsch     default:
6703d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6704552f7358SJed Brown     }
67059566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
6706552f7358SJed Brown   }
67071a271a75SMatthew G. Knepley   /* Cleanup points */
67089566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
67091a271a75SMatthew G. Knepley   /* Cleanup array */
67109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6711552f7358SJed Brown   PetscFunctionReturn(0);
6712552f7358SJed Brown }
6713552f7358SJed Brown 
6714cfb853baSMatthew G. Knepley PetscErrorCode DMPlexVecSetStar(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6715cfb853baSMatthew G. Knepley {
6716cfb853baSMatthew G. Knepley   const PetscInt *supp, *cone;
6717cfb853baSMatthew G. Knepley   PetscScalar    *a;
6718cfb853baSMatthew G. Knepley   PetscInt        dim, Ns, dof, off, n = 0;
6719cfb853baSMatthew G. Knepley 
6720cfb853baSMatthew G. Knepley   PetscFunctionBegin;
6721cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6722cfb853baSMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6723cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6724cfb853baSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
6725cfb853baSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) {
6726cfb853baSMatthew G. Knepley     PetscInt vStart, vEnd;
6727cfb853baSMatthew G. Knepley 
6728cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
6729cfb853baSMatthew 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);
6730cfb853baSMatthew G. Knepley   }
6731cfb853baSMatthew G. Knepley   PetscValidScalarPointer(values, 5);
6732cfb853baSMatthew G. Knepley 
6733cfb853baSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
6734cfb853baSMatthew G. Knepley   PetscCall(DMPlexGetSupportSize(dm, point, &Ns));
6735cfb853baSMatthew G. Knepley   PetscCall(DMPlexGetSupport(dm, point, &supp));
6736cfb853baSMatthew 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);
6737cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(v, &a));
6738cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetDof(section, point, &dof));
6739cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetOffset(section, point, &off));
6740cfb853baSMatthew G. Knepley   for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6741cfb853baSMatthew G. Knepley   for (PetscInt d = 0; d < dim; ++d) {
6742cfb853baSMatthew G. Knepley     // Left edge
6743cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetCone(dm, supp[2 * d + 0], &cone));
6744cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, cone[0], &dof));
6745cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(section, cone[0], &off));
6746cfb853baSMatthew G. Knepley     for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6747cfb853baSMatthew G. Knepley     // Right edge
6748cfb853baSMatthew G. Knepley     PetscCall(DMPlexGetCone(dm, supp[2 * d + 1], &cone));
6749cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, cone[1], &dof));
6750cfb853baSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(section, cone[1], &off));
6751cfb853baSMatthew G. Knepley     for (PetscInt i = 0; i < dof; ++i) a[off + i] = values[n++];
6752cfb853baSMatthew G. Knepley   }
6753cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(v, &a));
6754cfb853baSMatthew G. Knepley   PetscFunctionReturn(0);
6755cfb853baSMatthew G. Knepley }
6756cfb853baSMatthew G. Knepley 
67575f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
6758d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
6759d71ae5a4SJacob Faibussowitsch {
67605f790a90SMatthew G. Knepley   PetscFunctionBegin;
676111cc89d2SBarry Smith   *contains = PETSC_TRUE;
67625f790a90SMatthew G. Knepley   if (label) {
6763d6177c40SToby Isaac     PetscInt fdof;
67645f790a90SMatthew G. Knepley 
676511cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
676611cc89d2SBarry Smith     if (!*contains) {
67679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67685f790a90SMatthew G. Knepley       *offset += fdof;
676911cc89d2SBarry Smith       PetscFunctionReturn(0);
67705f790a90SMatthew G. Knepley     }
67715f790a90SMatthew G. Knepley   }
67725f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
67735f790a90SMatthew G. Knepley }
67745f790a90SMatthew G. Knepley 
677597529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
6776d71ae5a4SJacob 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)
6777d71ae5a4SJacob Faibussowitsch {
6778e07394fbSMatthew G. Knepley   PetscSection    clSection;
6779e07394fbSMatthew G. Knepley   IS              clPoints;
6780e07394fbSMatthew G. Knepley   PetscScalar    *array;
6781e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
678297529cf3SJed Brown   const PetscInt *clp;
6783e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
678497e99dd9SToby Isaac   PetscInt        offset = 0, f;
6785e07394fbSMatthew G. Knepley 
6786e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6787e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67889566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6789e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6790e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
67919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6792e07394fbSMatthew G. Knepley   /* Get points */
67939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6794e07394fbSMatthew G. Knepley   /* Get array */
67959566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6796e07394fbSMatthew G. Knepley   /* Get values */
6797e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
679897e99dd9SToby Isaac     const PetscInt    **perms = NULL;
679997e99dd9SToby Isaac     const PetscScalar **flips = NULL;
680011cc89d2SBarry Smith     PetscBool           contains;
680197e99dd9SToby Isaac 
6802e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6803e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
6804e07394fbSMatthew G. Knepley         PetscInt fdof;
68059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6806e07394fbSMatthew G. Knepley         offset += fdof;
6807e07394fbSMatthew G. Knepley       }
6808e07394fbSMatthew G. Knepley       continue;
6809e07394fbSMatthew G. Knepley     }
68109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6811e07394fbSMatthew G. Knepley     switch (mode) {
6812e07394fbSMatthew G. Knepley     case INSERT_VALUES:
681397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
681497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
681597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
681697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
681711cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
681811cc89d2SBarry Smith         if (!contains) continue;
68199566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
68209371c9d4SSatish Balay       }
68219371c9d4SSatish Balay       break;
6822e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
682397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
682497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
682597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
682697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
682711cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
682811cc89d2SBarry Smith         if (!contains) continue;
68299566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
68309371c9d4SSatish Balay       }
68319371c9d4SSatish Balay       break;
6832e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
683397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
683497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
683597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
683697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
683711cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
683811cc89d2SBarry Smith         if (!contains) continue;
68399566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
68409371c9d4SSatish Balay       }
68419371c9d4SSatish Balay       break;
6842e07394fbSMatthew G. Knepley     case ADD_VALUES:
684397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
684497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
684597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
684697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
684711cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
684811cc89d2SBarry Smith         if (!contains) continue;
68499566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
68509371c9d4SSatish Balay       }
68519371c9d4SSatish Balay       break;
6852e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
685397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
685497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
685597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
685697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
685711cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
685811cc89d2SBarry Smith         if (!contains) continue;
68599566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
68609371c9d4SSatish Balay       }
68619371c9d4SSatish Balay       break;
6862d71ae5a4SJacob Faibussowitsch     default:
6863d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6864e07394fbSMatthew G. Knepley     }
68659566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6866e07394fbSMatthew G. Knepley   }
6867e07394fbSMatthew G. Knepley   /* Cleanup points */
68689566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6869e07394fbSMatthew G. Knepley   /* Cleanup array */
68709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6871e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6872e07394fbSMatthew G. Knepley }
6873e07394fbSMatthew G. Knepley 
6874d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6875d71ae5a4SJacob Faibussowitsch {
6876552f7358SJed Brown   PetscMPIInt rank;
6877552f7358SJed Brown   PetscInt    i, j;
6878552f7358SJed Brown 
6879552f7358SJed Brown   PetscFunctionBegin;
68809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
688163a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
688263a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
688363a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6884b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6885557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6886b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
68879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6888b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6889519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
68909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
6891552f7358SJed Brown #else
68929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
6893552f7358SJed Brown #endif
6894552f7358SJed Brown     }
68959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6896552f7358SJed Brown   }
6897552f7358SJed Brown   PetscFunctionReturn(0);
6898552f7358SJed Brown }
6899552f7358SJed Brown 
690005586334SMatthew G. Knepley /*
690105586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
690205586334SMatthew G. Knepley 
690305586334SMatthew G. Knepley   Input Parameters:
690405586334SMatthew G. Knepley + section - The section for this data layout
690536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
690605586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
690705586334SMatthew G. Knepley . off     - The global offset of this point
690805586334SMatthew G. Knepley . loff    - The local offset of each field
6909a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
691005586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
691105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
691205586334SMatthew G. Knepley 
691305586334SMatthew G. Knepley   Output Parameter:
691405586334SMatthew G. Knepley . indices - Indices for dofs on this point
691505586334SMatthew G. Knepley 
691605586334SMatthew G. Knepley   Level: developer
691705586334SMatthew G. Knepley 
691805586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
691905586334SMatthew G. Knepley */
6920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6921d71ae5a4SJacob Faibussowitsch {
6922e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6923552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6924552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6925552f7358SJed Brown   PetscInt        cind = 0, k;
6926552f7358SJed Brown 
6927552f7358SJed Brown   PetscFunctionBegin;
692808401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
69299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
69309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6931552f7358SJed Brown   if (!cdof || setBC) {
693205586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
693305586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
693405586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
693505586334SMatthew G. Knepley 
693605586334SMatthew G. Knepley       indices[ind] = off + k;
6937552f7358SJed Brown     }
6938552f7358SJed Brown   } else {
69399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
69404acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
694105586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
694205586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
694305586334SMatthew G. Knepley 
69444acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
69454acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
694605586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
69474acb8e1eSToby Isaac         ++cind;
69484acb8e1eSToby Isaac       } else {
694936fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6950552f7358SJed Brown       }
6951552f7358SJed Brown     }
6952552f7358SJed Brown   }
6953e6ccafaeSMatthew G Knepley   *loff += dof;
6954552f7358SJed Brown   PetscFunctionReturn(0);
6955552f7358SJed Brown }
6956552f7358SJed Brown 
69577e29afd2SMatthew G. Knepley /*
695836fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
69597e29afd2SMatthew G. Knepley 
696036fa2b79SJed Brown  Input Parameters:
696136fa2b79SJed Brown + section - a section (global or local)
696236fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
696336fa2b79SJed Brown . point - point within section
696436fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
696536fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
696636fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
696736fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
696836fa2b79SJed Brown . permsoff - offset
696936fa2b79SJed Brown - indperm - index permutation
697036fa2b79SJed Brown 
697136fa2b79SJed Brown  Output Parameter:
697236fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
697336fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
697436fa2b79SJed Brown 
697536fa2b79SJed Brown  Notes:
697636fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
697736fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
697836fa2b79SJed Brown  in the local vector.
697936fa2b79SJed Brown 
698036fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
698136fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
698236fa2b79SJed Brown 
698336fa2b79SJed Brown  Developer Note:
698436fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
698536fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
698636fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
698736fa2b79SJed Brown 
698836fa2b79SJed Brown  Example:
698936fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
699036fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
699136fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
699236fa2b79SJed 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.
699336fa2b79SJed Brown 
699436fa2b79SJed Brown  Level: developer
69957e29afd2SMatthew G. Knepley */
6996d71ae5a4SJacob 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[])
6997d71ae5a4SJacob Faibussowitsch {
6998552f7358SJed Brown   PetscInt numFields, foff, f;
6999552f7358SJed Brown 
7000552f7358SJed Brown   PetscFunctionBegin;
700108401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
70029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7003552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
70044acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7005552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
70064acb8e1eSToby Isaac     PetscInt        cind = 0, b;
70074acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7008552f7358SJed Brown 
70099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7011552f7358SJed Brown     if (!cfdof || setBC) {
701205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
701305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
701405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
701505586334SMatthew G. Knepley 
701605586334SMatthew G. Knepley         indices[ind] = off + foff + b;
701705586334SMatthew G. Knepley       }
7018552f7358SJed Brown     } else {
70199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
702005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
702105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
702205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
702305586334SMatthew G. Knepley 
70244acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
702505586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7026552f7358SJed Brown           ++cind;
7027552f7358SJed Brown         } else {
702836fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7029552f7358SJed Brown         }
7030552f7358SJed Brown       }
7031552f7358SJed Brown     }
703236fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7033552f7358SJed Brown     foffs[f] += fdof;
7034552f7358SJed Brown   }
7035552f7358SJed Brown   PetscFunctionReturn(0);
7036552f7358SJed Brown }
7037552f7358SJed Brown 
70387e29afd2SMatthew G. Knepley /*
70397e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
70407e29afd2SMatthew G. Knepley 
70417e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7042645102dcSJed Brown 
7043645102dcSJed Brown  Notes:
7044645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7045645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
70467e29afd2SMatthew G. Knepley */
7047d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7048d71ae5a4SJacob Faibussowitsch {
70497e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
70507e29afd2SMatthew G. Knepley 
70517e29afd2SMatthew G. Knepley   PetscFunctionBegin;
70529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
70537e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
70547e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
70557e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
70567e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
70577e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
70587e29afd2SMatthew G. Knepley 
70599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
70619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7062645102dcSJed Brown     if (!cfdof) {
706305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
706405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
706505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
706605586334SMatthew G. Knepley 
706705586334SMatthew G. Knepley         indices[ind] = foff + b;
706805586334SMatthew G. Knepley       }
70697e29afd2SMatthew G. Knepley     } else {
70709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
707105586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
707205586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
707305586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
707405586334SMatthew G. Knepley 
70757e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
707605586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
70777e29afd2SMatthew G. Knepley           ++cind;
70787e29afd2SMatthew G. Knepley         } else {
707905586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
70807e29afd2SMatthew G. Knepley         }
70817e29afd2SMatthew G. Knepley       }
70827e29afd2SMatthew G. Knepley     }
70837e29afd2SMatthew G. Knepley     foffs[f] += fdof;
70847e29afd2SMatthew G. Knepley   }
70857e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
70867e29afd2SMatthew G. Knepley }
70877e29afd2SMatthew G. Knepley 
7088d71ae5a4SJacob 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)
7089d71ae5a4SJacob Faibussowitsch {
7090d3d1a6afSToby Isaac   Mat             cMat;
7091d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7092d3d1a6afSToby Isaac   IS              aIS;
7093d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7094d3d1a6afSToby Isaac   const PetscInt *anchors;
7095e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7096d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7097d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7098d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7099d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7100d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7101d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7102d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
71036ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7104d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7105d3d1a6afSToby Isaac 
7106d3d1a6afSToby Isaac   PetscFunctionBegin;
7107d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7108d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
71099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7110d3d1a6afSToby Isaac 
71119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7112d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7113d3d1a6afSToby Isaac   if (aSec) {
71149566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
71159566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
71169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7117d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7118d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7119d3d1a6afSToby Isaac      * into the global matrix anyway) */
7120d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7121d3d1a6afSToby Isaac       PetscInt b    = points[p];
71224b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7123d3d1a6afSToby Isaac 
71249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7125ad540459SPierre Jolivet       if (!bSecDof) continue;
712648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7127d3d1a6afSToby Isaac       if (bDof) {
7128d3d1a6afSToby Isaac         /* this point is constrained */
7129d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7130d3d1a6afSToby Isaac         PetscInt bOff, q;
7131d3d1a6afSToby Isaac 
7132d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7133d3d1a6afSToby Isaac         newNumPoints += bDof;
71349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7135d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7136d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7137d3d1a6afSToby Isaac           PetscInt aDof;
7138d3d1a6afSToby Isaac 
71399566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7140d3d1a6afSToby Isaac           newNumIndices += aDof;
7141d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7142d3d1a6afSToby Isaac             PetscInt fDof;
7143d3d1a6afSToby Isaac 
71449566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7145d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7146d3d1a6afSToby Isaac           }
7147d3d1a6afSToby Isaac         }
71489371c9d4SSatish Balay       } else {
7149d3d1a6afSToby Isaac         /* this point is not constrained */
7150d3d1a6afSToby Isaac         newNumPoints++;
71514b2f2278SToby Isaac         newNumIndices += bSecDof;
7152d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7153d3d1a6afSToby Isaac           PetscInt fDof;
7154d3d1a6afSToby Isaac 
71559566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7156d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7157d3d1a6afSToby Isaac         }
7158d3d1a6afSToby Isaac       }
7159d3d1a6afSToby Isaac     }
7160d3d1a6afSToby Isaac   }
7161d3d1a6afSToby Isaac   if (!anyConstrained) {
716272b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
716372b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
716472b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
716572b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
71669566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
7167d3d1a6afSToby Isaac     PetscFunctionReturn(0);
7168d3d1a6afSToby Isaac   }
7169d3d1a6afSToby Isaac 
71706ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
71716ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
71726ecaa68aSToby Isaac 
7173f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7174d3d1a6afSToby Isaac 
71756ecaa68aSToby Isaac   if (!outPoints && !outValues) {
71766ecaa68aSToby Isaac     if (offsets) {
7177ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
71786ecaa68aSToby Isaac     }
71799566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
71806ecaa68aSToby Isaac     PetscFunctionReturn(0);
71816ecaa68aSToby Isaac   }
71826ecaa68aSToby Isaac 
71831dca8a05SBarry 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);
7184d3d1a6afSToby Isaac 
71859566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7186d3d1a6afSToby Isaac 
7187d3d1a6afSToby Isaac   /* workspaces */
7188d3d1a6afSToby Isaac   if (numFields) {
7189d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
71909566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
71919566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7192d3d1a6afSToby Isaac     }
71939371c9d4SSatish Balay   } else {
71949566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
71959566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7196d3d1a6afSToby Isaac   }
7197d3d1a6afSToby Isaac 
7198d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7199d3d1a6afSToby Isaac   if (numFields) {
72004b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
72014b2f2278SToby Isaac 
7202d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7203d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
72044b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7205d3d1a6afSToby Isaac 
72069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
72074b2f2278SToby Isaac       if (!bSecDof) {
72084b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
72094b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
72104b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
72114b2f2278SToby Isaac         }
72124b2f2278SToby Isaac         continue;
72134b2f2278SToby Isaac       }
721448a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7215d3d1a6afSToby Isaac       if (bDof) {
7216d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7217d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7218d3d1a6afSToby Isaac 
72199566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
72209566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7221d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7222d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7223d3d1a6afSToby Isaac             PetscInt aFDof;
7224d3d1a6afSToby Isaac 
72259566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7226d3d1a6afSToby Isaac             allFDof += aFDof;
7227d3d1a6afSToby Isaac           }
7228d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7229d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7230d3d1a6afSToby Isaac         }
72319371c9d4SSatish Balay       } else {
7232d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7233d3d1a6afSToby Isaac           PetscInt fDof;
7234d3d1a6afSToby Isaac 
72359566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7236d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7237d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7238d3d1a6afSToby Isaac         }
7239d3d1a6afSToby Isaac       }
7240d3d1a6afSToby Isaac     }
72414b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
72424b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
72434b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7244d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7245d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7246d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7247d3d1a6afSToby Isaac       }
724819f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
724919f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
72509566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7251d3d1a6afSToby Isaac     }
72529371c9d4SSatish Balay   } else {
7253d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7254d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
72554b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7256d3d1a6afSToby Isaac 
72579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
72584b2f2278SToby Isaac       if (!bSecDof) {
72594b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
72604b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
72614b2f2278SToby Isaac         continue;
72624b2f2278SToby Isaac       }
726348a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7264d3d1a6afSToby Isaac       if (bDof) {
72654b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7266d3d1a6afSToby Isaac 
72679566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7268d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7269d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7270d3d1a6afSToby Isaac 
72719566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7272d3d1a6afSToby Isaac           allDof += aDof;
7273d3d1a6afSToby Isaac         }
7274d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
72754b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
72769371c9d4SSatish Balay       } else {
72774b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7278d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7279d3d1a6afSToby Isaac       }
7280d3d1a6afSToby Isaac     }
7281d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7282d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7283d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7284d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7285d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7286d3d1a6afSToby Isaac     }
72879566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7288d3d1a6afSToby Isaac   }
7289d3d1a6afSToby Isaac 
72906ecaa68aSToby Isaac   /* output arrays */
72919566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
72926ecaa68aSToby Isaac 
7293d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
72949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
72959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
72969566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
72979566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7298d3d1a6afSToby Isaac   if (numFields) {
7299d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7300d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7301d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
73024b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7303d3d1a6afSToby Isaac 
73049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7305ad540459SPierre Jolivet       if (!bSecDof) continue;
730648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7307d3d1a6afSToby Isaac       if (bDof) {
7308d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7309d3d1a6afSToby Isaac 
7310d3d1a6afSToby Isaac         fStart[0] = 0;
7311d3d1a6afSToby Isaac         fEnd[0]   = 0;
7312d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7313d3d1a6afSToby Isaac           PetscInt fDof;
7314d3d1a6afSToby Isaac 
73159566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7316d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7317d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7318d3d1a6afSToby Isaac         }
73199566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
73209566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7321d3d1a6afSToby Isaac 
7322d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7323d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7324d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7325d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7326d3d1a6afSToby Isaac 
7327d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7328d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7329d3d1a6afSToby Isaac         }
73309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7331d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7332d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7333d3d1a6afSToby Isaac 
7334d3d1a6afSToby 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 */
7335d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7336d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
73379566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
73389566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7339d3d1a6afSToby Isaac         }
7340d3d1a6afSToby Isaac         newP += bDof;
7341d3d1a6afSToby Isaac 
73426ecaa68aSToby Isaac         if (outValues) {
7343d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
734448a46eb9SPierre 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]));
7345d3d1a6afSToby Isaac         }
73469371c9d4SSatish Balay       } else {
7347d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7348d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7349d3d1a6afSToby Isaac         newP++;
7350d3d1a6afSToby Isaac       }
7351d3d1a6afSToby Isaac     }
7352d3d1a6afSToby Isaac   } else {
7353d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7354d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7355d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
73564b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7357d3d1a6afSToby Isaac 
73589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7359ad540459SPierre Jolivet       if (!bSecDof) continue;
736048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7361d3d1a6afSToby Isaac       if (bDof) {
7362d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7363d3d1a6afSToby Isaac 
73649566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
73659566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7366d3d1a6afSToby Isaac 
73679566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7368d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7369d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7370d3d1a6afSToby Isaac 
7371d3d1a6afSToby 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 */
7372d3d1a6afSToby Isaac 
7373d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7374d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
73759566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
73769566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7377d3d1a6afSToby Isaac         }
7378d3d1a6afSToby Isaac         newP += bDof;
7379d3d1a6afSToby Isaac 
7380d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
738148a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
73829371c9d4SSatish Balay       } else {
7383d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7384d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7385d3d1a6afSToby Isaac         newP++;
7386d3d1a6afSToby Isaac       }
7387d3d1a6afSToby Isaac     }
7388d3d1a6afSToby Isaac   }
7389d3d1a6afSToby Isaac 
73906ecaa68aSToby Isaac   if (outValues) {
73919566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
73929566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7393d3d1a6afSToby Isaac     /* multiply constraints on the right */
7394d3d1a6afSToby Isaac     if (numFields) {
7395d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7396d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7397d3d1a6afSToby Isaac 
7398d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7399d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7400d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7401d3d1a6afSToby Isaac           PetscInt c, r, k;
7402d3d1a6afSToby Isaac           PetscInt dof;
7403d3d1a6afSToby Isaac 
74049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7405ad540459SPierre Jolivet           if (!dof) continue;
7406d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7407d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7408d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7409d3d1a6afSToby Isaac 
7410d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7411d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7412ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7413d3d1a6afSToby Isaac               }
7414d3d1a6afSToby Isaac             }
74159371c9d4SSatish Balay           } else {
7416d3d1a6afSToby Isaac             /* copy this column as is */
7417d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7418ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7419d3d1a6afSToby Isaac             }
7420d3d1a6afSToby Isaac           }
7421d3d1a6afSToby Isaac           oldOff += dof;
7422d3d1a6afSToby Isaac         }
7423d3d1a6afSToby Isaac       }
74249371c9d4SSatish Balay     } else {
7425d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7426d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7427d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7428d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7429d3d1a6afSToby Isaac         PetscInt c, r, k;
7430d3d1a6afSToby Isaac         PetscInt dof;
7431d3d1a6afSToby Isaac 
74329566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7433ad540459SPierre Jolivet         if (!dof) continue;
7434d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7435d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7436d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7437d3d1a6afSToby Isaac 
7438d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7439d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7440ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7441d3d1a6afSToby Isaac             }
7442d3d1a6afSToby Isaac           }
74439371c9d4SSatish Balay         } else {
7444d3d1a6afSToby Isaac           /* copy this column as is */
7445d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7446ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7447d3d1a6afSToby Isaac           }
7448d3d1a6afSToby Isaac         }
7449d3d1a6afSToby Isaac         oldOff += dof;
7450d3d1a6afSToby Isaac       }
7451d3d1a6afSToby Isaac     }
7452d3d1a6afSToby Isaac 
74536ecaa68aSToby Isaac     if (multiplyLeft) {
74549566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
74559566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7456d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7457d3d1a6afSToby Isaac       if (numFields) {
7458d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7459d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7460d3d1a6afSToby Isaac 
7461d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7462d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7463d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7464d3d1a6afSToby Isaac             PetscInt c, r, k;
7465d3d1a6afSToby Isaac             PetscInt dof;
7466d3d1a6afSToby Isaac 
74679566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7468d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7469d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7470d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7471d3d1a6afSToby Isaac 
7472d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7473d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7474ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7475d3d1a6afSToby Isaac                 }
7476d3d1a6afSToby Isaac               }
74779371c9d4SSatish Balay             } else {
7478d3d1a6afSToby Isaac               /* copy this row as is */
7479d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7480ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7481d3d1a6afSToby Isaac               }
7482d3d1a6afSToby Isaac             }
7483d3d1a6afSToby Isaac             oldOff += dof;
7484d3d1a6afSToby Isaac           }
7485d3d1a6afSToby Isaac         }
74869371c9d4SSatish Balay       } else {
7487d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7488d3d1a6afSToby Isaac 
7489d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7490d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7491d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7492d3d1a6afSToby Isaac           PetscInt c, r, k;
7493d3d1a6afSToby Isaac           PetscInt dof;
7494d3d1a6afSToby Isaac 
74959566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7496d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7497d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7498d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7499d3d1a6afSToby Isaac 
7500d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7501d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7502ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7503d3d1a6afSToby Isaac               }
7504d3d1a6afSToby Isaac             }
75059371c9d4SSatish Balay           } else {
7506d3d1a6afSToby Isaac             /* copy this row as is */
75079fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7508ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7509d3d1a6afSToby Isaac             }
7510d3d1a6afSToby Isaac           }
7511d3d1a6afSToby Isaac           oldOff += dof;
7512d3d1a6afSToby Isaac         }
7513d3d1a6afSToby Isaac       }
7514d3d1a6afSToby Isaac 
75159566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
75169371c9d4SSatish Balay     } else {
75176ecaa68aSToby Isaac       newValues = tmpValues;
75186ecaa68aSToby Isaac     }
75196ecaa68aSToby Isaac   }
75206ecaa68aSToby Isaac 
7521d3d1a6afSToby Isaac   /* clean up */
75229566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
75239566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
75246ecaa68aSToby Isaac 
7525d3d1a6afSToby Isaac   if (numFields) {
7526d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
75279566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
75289566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
75299566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7530d3d1a6afSToby Isaac     }
75319371c9d4SSatish Balay   } else {
75329566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
75339566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
75349566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7535d3d1a6afSToby Isaac   }
75369566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7537d3d1a6afSToby Isaac 
7538d3d1a6afSToby Isaac   /* output */
75396ecaa68aSToby Isaac   if (outPoints) {
7540d3d1a6afSToby Isaac     *outPoints = newPoints;
75419371c9d4SSatish Balay   } else {
75429566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
75436ecaa68aSToby Isaac   }
7544ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7545ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
7546d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7547d3d1a6afSToby Isaac }
7548d3d1a6afSToby Isaac 
75494a1e0b3eSMatthew G. Knepley /*@C
755071f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
75517cd05799SMatthew G. Knepley 
75527cd05799SMatthew G. Knepley   Not collective
75537cd05799SMatthew G. Knepley 
75547cd05799SMatthew G. Knepley   Input Parameters:
7555a1cb98faSBarry Smith + dm         - The `DM`
7556a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7557a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
755871f0bbf9SMatthew G. Knepley . point      - The point defining the closure
755971f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
75607cd05799SMatthew G. Knepley 
756171f0bbf9SMatthew G. Knepley   Output Parameters:
756271f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
756371f0bbf9SMatthew G. Knepley . indices    - The dof indices
756471f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
756571f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
75667cd05799SMatthew G. Knepley 
7567a1cb98faSBarry Smith   Level: advanced
756836fa2b79SJed Brown 
7569a1cb98faSBarry Smith   Notes:
7570a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7571a1cb98faSBarry Smith 
7572a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
757336fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
757436fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
757536fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
757636fa2b79SJed Brown   indices (with the above semantics) are implied.
75777cd05799SMatthew G. Knepley 
7578a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7579a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
75804a1e0b3eSMatthew G. Knepley @*/
7581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7582d71ae5a4SJacob Faibussowitsch {
758371f0bbf9SMatthew G. Knepley   /* Closure ordering */
75847773e69fSMatthew G. Knepley   PetscSection    clSection;
75857773e69fSMatthew G. Knepley   IS              clPoints;
758671f0bbf9SMatthew G. Knepley   const PetscInt *clp;
758771f0bbf9SMatthew G. Knepley   PetscInt       *points;
758871f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
758971f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
75904acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
759171f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
759271f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
759371f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
759471f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
759571f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
759671f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
759771f0bbf9SMatthew G. Knepley 
759871f0bbf9SMatthew G. Knepley   PetscInt *idx;
759971f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
760071f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
76017773e69fSMatthew G. Knepley 
760271f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
76037773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
76047773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
760536fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7606dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
760771f0bbf9SMatthew G. Knepley   if (indices) PetscValidPointer(indices, 7);
7608dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
760971f0bbf9SMatthew G. Knepley   if (values) PetscValidPointer(values, 9);
76109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
761163a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
76129566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
761371f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
76149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7615c459fbc1SJed Brown   if (useClPerm) {
7616c459fbc1SJed Brown     PetscInt depth, clsize;
76179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7618c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7619c459fbc1SJed Brown       PetscInt dof;
76209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7621c459fbc1SJed Brown       clsize += dof;
7622c459fbc1SJed Brown     }
76239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7624c459fbc1SJed Brown   }
762571f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
762671f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
76277773e69fSMatthew G. Knepley     PetscInt dof, fdof;
76287773e69fSMatthew G. Knepley 
76299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
76307773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
76319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
76327773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
76337773e69fSMatthew G. Knepley     }
763471f0bbf9SMatthew G. Knepley     Ni += dof;
76357773e69fSMatthew G. Knepley   }
76367773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
76371dca8a05SBarry 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);
763871f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
763971f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
76409566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
76419566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
764271f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
764371f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
764471f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
76456ecaa68aSToby Isaac 
764671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
764771f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
764871f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
764971f0bbf9SMatthew G. Knepley 
76509566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
76519566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
765271f0bbf9SMatthew G. Knepley         if (flip) {
765371f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
765471f0bbf9SMatthew G. Knepley 
765571f0bbf9SMatthew G. Knepley           if (!valCopy) {
76569566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
765771f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
765871f0bbf9SMatthew G. Knepley             *values = valCopy;
765971f0bbf9SMatthew G. Knepley           }
766071f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
766171f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
766271f0bbf9SMatthew G. Knepley 
766371f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
766471f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
766571f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
76666ecaa68aSToby Isaac             }
76676ecaa68aSToby Isaac           }
766871f0bbf9SMatthew G. Knepley         }
766971f0bbf9SMatthew G. Knepley         foffset += fdof;
767071f0bbf9SMatthew G. Knepley       }
767171f0bbf9SMatthew G. Knepley     }
767271f0bbf9SMatthew G. Knepley   }
767371f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
76749566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
767571f0bbf9SMatthew G. Knepley   if (NclC) {
76769566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
767771f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
76789566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
76799566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
768071f0bbf9SMatthew G. Knepley     }
768171f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
76829566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
76839566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
768471f0bbf9SMatthew G. Knepley     }
76859566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
768671f0bbf9SMatthew G. Knepley     Ncl    = NclC;
768771f0bbf9SMatthew G. Knepley     Ni     = NiC;
768871f0bbf9SMatthew G. Knepley     points = pointsC;
768971f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
769071f0bbf9SMatthew G. Knepley   }
769171f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
76929566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
769371f0bbf9SMatthew G. Knepley   if (Nf) {
769471f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
769571f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
769671f0bbf9SMatthew G. Knepley 
76979371c9d4SSatish Balay     if (outOffsets) {
76989371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
76999371c9d4SSatish Balay     }
77009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
770171f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
770271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
770371f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
770471f0bbf9SMatthew G. Knepley 
77059566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
77067773e69fSMatthew G. Knepley       }
77077773e69fSMatthew G. Knepley     } else {
770871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
770971f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
771071f0bbf9SMatthew G. Knepley 
77119566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
771271f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
771371f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
771471f0bbf9SMatthew G. Knepley          * global section. */
77159566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
771671f0bbf9SMatthew G. Knepley       }
771771f0bbf9SMatthew G. Knepley     }
771871f0bbf9SMatthew G. Knepley   } else {
771971f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
772071f0bbf9SMatthew G. Knepley 
772171f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
772271f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
77234acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
77244acb8e1eSToby Isaac 
77259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
772671f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
772771f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
77289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
77297773e69fSMatthew G. Knepley     }
77307773e69fSMatthew G. Knepley   }
773171f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
773271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
77339566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
77349566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
77354acb8e1eSToby Isaac   }
773671f0bbf9SMatthew G. Knepley   if (NclC) {
77379566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
77387773e69fSMatthew G. Knepley   } else {
77399566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
77407773e69fSMatthew G. Knepley   }
774171f0bbf9SMatthew G. Knepley 
774271f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
774371f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
77447773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
77457773e69fSMatthew G. Knepley }
77467773e69fSMatthew G. Knepley 
77477cd05799SMatthew G. Knepley /*@C
774871f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
77497cd05799SMatthew G. Knepley 
77507cd05799SMatthew G. Knepley   Not collective
77517cd05799SMatthew G. Knepley 
77527cd05799SMatthew G. Knepley   Input Parameters:
7753a1cb98faSBarry Smith + dm         - The `DM`
7754a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7755a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
775671f0bbf9SMatthew G. Knepley . point      - The point defining the closure
775771f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
775871f0bbf9SMatthew G. Knepley 
775971f0bbf9SMatthew G. Knepley   Output Parameters:
776071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
776171f0bbf9SMatthew G. Knepley . indices    - The dof indices
776271f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
776371f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
776471f0bbf9SMatthew G. Knepley 
7765a1cb98faSBarry Smith   Level: advanced
776671f0bbf9SMatthew G. Knepley 
7767a1cb98faSBarry Smith   Notes:
7768a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
7769a1cb98faSBarry Smith 
7770a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
777171f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
777271f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
777371f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
777471f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
77757cd05799SMatthew G. Knepley 
7776a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
77777cd05799SMatthew G. Knepley @*/
7778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7779d71ae5a4SJacob Faibussowitsch {
77807773e69fSMatthew G. Knepley   PetscFunctionBegin;
77817773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7782064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
77839566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
77847773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
77857773e69fSMatthew G. Knepley }
77867773e69fSMatthew G. Knepley 
77877f5d1fdeSMatthew G. Knepley /*@C
77887f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
77897f5d1fdeSMatthew G. Knepley 
77907f5d1fdeSMatthew G. Knepley   Not collective
77917f5d1fdeSMatthew G. Knepley 
77927f5d1fdeSMatthew G. Knepley   Input Parameters:
7793a1cb98faSBarry Smith + dm - The `DM`
7794ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7795ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
77967f5d1fdeSMatthew G. Knepley . A - The matrix
7797a1cb98faSBarry Smith . point - The point in the `DM`
77987f5d1fdeSMatthew G. Knepley . values - The array of values
7799a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
78007f5d1fdeSMatthew G. Knepley 
78017f5d1fdeSMatthew G. Knepley   Level: intermediate
78027f5d1fdeSMatthew G. Knepley 
7803a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
78047f5d1fdeSMatthew G. Knepley @*/
7805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7806d71ae5a4SJacob Faibussowitsch {
7807552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
7808552f7358SJed Brown   PetscInt          *indices;
780971f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
781071f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7811552f7358SJed Brown   PetscErrorCode     ierr;
7812552f7358SJed Brown 
7813552f7358SJed Brown   PetscFunctionBegin;
7814552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78159566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
78163dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
78179566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
78183dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
78193dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7820552f7358SJed Brown 
78219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78220d644c17SKarl Rupp 
78239566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7824d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
78254a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7826552f7358SJed Brown   if (ierr) {
7827552f7358SJed Brown     PetscMPIInt rank;
7828552f7358SJed Brown 
78299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
78309566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
78319566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
78329566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78339566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7834c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
7835552f7358SJed Brown   }
78364a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
78374a1e0b3eSMatthew G. Knepley     PetscInt i;
78389566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
783963a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
78409566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
78414a1e0b3eSMatthew G. Knepley   }
784271f0bbf9SMatthew G. Knepley 
78439566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78449566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
784571f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
78464acb8e1eSToby Isaac }
784771f0bbf9SMatthew G. Knepley 
78484a1e0b3eSMatthew G. Knepley /*@C
78494a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
78504a1e0b3eSMatthew G. Knepley 
78514a1e0b3eSMatthew G. Knepley   Not collective
78524a1e0b3eSMatthew G. Knepley 
78534a1e0b3eSMatthew G. Knepley   Input Parameters:
7854a1cb98faSBarry Smith + dmRow - The `DM` for the row fields
78554a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
78564a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
7857a1cb98faSBarry Smith . dmCol - The `DM` for the column fields
78584a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
78594a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
78604a1e0b3eSMatthew G. Knepley . A - The matrix
7861a1cb98faSBarry Smith . point - The point in the `DM`
78624a1e0b3eSMatthew G. Knepley . values - The array of values
7863a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
78644a1e0b3eSMatthew G. Knepley 
78654a1e0b3eSMatthew G. Knepley   Level: intermediate
78664a1e0b3eSMatthew G. Knepley 
7867a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
78684a1e0b3eSMatthew G. Knepley @*/
7869d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7870d71ae5a4SJacob Faibussowitsch {
787171f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
787271f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
787371f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
787471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
787571f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
787671f0bbf9SMatthew G. Knepley 
787771f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
787871f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
78799566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
788071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
78819566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
788271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
788371f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
78849566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
788571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
78869566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
788771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
788871f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
788971f0bbf9SMatthew G. Knepley 
78909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
78919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
789271f0bbf9SMatthew G. Knepley 
78939566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7894d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
78954a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
789671f0bbf9SMatthew G. Knepley   if (ierr) {
789771f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
789871f0bbf9SMatthew G. Knepley 
78999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
79009566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
79019566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
79029566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79039566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
79049566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7905d3d1a6afSToby Isaac   }
790671f0bbf9SMatthew G. Knepley 
79079566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79089566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
79099566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7910552f7358SJed Brown   PetscFunctionReturn(0);
7911552f7358SJed Brown }
7912552f7358SJed Brown 
7913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7914d71ae5a4SJacob Faibussowitsch {
7915de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
7916de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7917de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7918de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
791917c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7920de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7921412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
79224ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7923de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7924de41b84cSMatthew G. Knepley 
7925de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7926de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7927de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
79289566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7929de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
79309566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7931de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
79329566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7933de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
79349566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7935de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7936de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
79379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
793863a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
79399566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
79409566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7941de41b84cSMatthew G. Knepley   /* Column indices */
79429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79434ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7944de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7945de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
79469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7947de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
7948de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7949de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
7950de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
7951de41b84cSMatthew G. Knepley       ++q;
7952de41b84cSMatthew G. Knepley     }
7953de41b84cSMatthew G. Knepley   }
7954de41b84cSMatthew G. Knepley   numCPoints = q;
7955de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
7956de41b84cSMatthew G. Knepley     PetscInt fdof;
7957de41b84cSMatthew G. Knepley 
79589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
79594ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7960de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
79619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7962de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
7963de41b84cSMatthew G. Knepley     }
7964de41b84cSMatthew G. Knepley     numCIndices += dof;
7965de41b84cSMatthew G. Knepley   }
7966de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
7967de41b84cSMatthew G. Knepley   /* Row indices */
79689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7969412e9a14SMatthew G. Knepley   {
7970012bc364SMatthew G. Knepley     DMPlexTransform tr;
7971012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7972012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7973012bc364SMatthew G. Knepley 
79749566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
79759566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
79769566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7977012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
79789566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7979412e9a14SMatthew G. Knepley   }
79809566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
7981de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7982de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
79839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7984de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
79859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
7986de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
7987de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
79889566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
79894ca5e9f5SMatthew G. Knepley         if (!dof) continue;
79909371c9d4SSatish Balay         for (s = 0; s < q; ++s)
79919371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
79924ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7993de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
7994de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
7995de41b84cSMatthew G. Knepley         ++q;
7996de41b84cSMatthew G. Knepley       }
7997de41b84cSMatthew G. Knepley     }
79989566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7999de41b84cSMatthew G. Knepley   }
8000de41b84cSMatthew G. Knepley   numFPoints = q;
8001de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8002de41b84cSMatthew G. Knepley     PetscInt fdof;
8003de41b84cSMatthew G. Knepley 
80049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
80054ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8006de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
80079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8008de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8009de41b84cSMatthew G. Knepley     }
8010de41b84cSMatthew G. Knepley     numFIndices += dof;
8011de41b84cSMatthew G. Knepley   }
8012de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8013de41b84cSMatthew G. Knepley 
80141dca8a05SBarry 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);
80151dca8a05SBarry 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);
80169566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80179566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8018de41b84cSMatthew G. Knepley   if (numFields) {
80194acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
80204acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
80214acb8e1eSToby Isaac 
80224acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8025de41b84cSMatthew G. Knepley     }
80264acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
80279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
80289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
80294acb8e1eSToby Isaac     }
80304acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
80319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
80329566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
80334acb8e1eSToby Isaac     }
80344acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80359566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80369566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8037de41b84cSMatthew G. Knepley     }
8038de41b84cSMatthew G. Knepley   } else {
80394acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
80404acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
80414acb8e1eSToby Isaac 
80429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
80439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
80444acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
80454acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
80464acb8e1eSToby Isaac 
80479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
80489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8049de41b84cSMatthew G. Knepley     }
80504acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
80514acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
80524acb8e1eSToby Isaac 
80539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
80549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8055de41b84cSMatthew G. Knepley     }
80569566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
80579566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8058de41b84cSMatthew G. Knepley   }
80599566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
80604acb8e1eSToby Isaac   /* TODO: flips */
8061d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8062de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8063de41b84cSMatthew G. Knepley   if (ierr) {
8064de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8065de41b84cSMatthew G. Knepley 
80669566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
80679566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
80689566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
80699566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80709566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8071de41b84cSMatthew G. Knepley   }
80729566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
80739566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
80749566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80759566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8076de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
8077de41b84cSMatthew G. Knepley }
8078de41b84cSMatthew G. Knepley 
8079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8080d71ae5a4SJacob Faibussowitsch {
80817c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
80827c927364SMatthew G. Knepley   PetscInt       *cpoints = NULL;
80837c927364SMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
808417c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8085412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
80867c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
80877c927364SMatthew G. Knepley 
80887c927364SMatthew G. Knepley   PetscFunctionBegin;
80897c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
80907c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
80919566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
80927c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
80939566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
80947c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
80959566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
80967c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
80979566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
80987c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
80999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
810063a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
81019566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
81029566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
81037c927364SMatthew G. Knepley   /* Column indices */
81049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81057c927364SMatthew G. Knepley   maxFPoints = numCPoints;
81067c927364SMatthew G. Knepley   /* Compress out points not in the section */
81077c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
81089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
81097c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
81107c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
81117c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
81127c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
81137c927364SMatthew G. Knepley       ++q;
81147c927364SMatthew G. Knepley     }
81157c927364SMatthew G. Knepley   }
81167c927364SMatthew G. Knepley   numCPoints = q;
81177c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
81187c927364SMatthew G. Knepley     PetscInt fdof;
81197c927364SMatthew G. Knepley 
81209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
81217c927364SMatthew G. Knepley     if (!dof) continue;
81227c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
81239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
81247c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
81257c927364SMatthew G. Knepley     }
81267c927364SMatthew G. Knepley     numCIndices += dof;
81277c927364SMatthew G. Knepley   }
81287c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
81297c927364SMatthew G. Knepley   /* Row indices */
81309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8131412e9a14SMatthew G. Knepley   {
8132012bc364SMatthew G. Knepley     DMPlexTransform tr;
8133012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8134012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8135012bc364SMatthew G. Knepley 
81369566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
81379566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
81389566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8139012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
81409566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8141412e9a14SMatthew G. Knepley   }
81429566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
81437c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
81447c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
81459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
81467c927364SMatthew G. Knepley     /* Compress out points not in the section */
81479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
81487c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
81497c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
81509566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
81517c927364SMatthew G. Knepley         if (!dof) continue;
81529371c9d4SSatish Balay         for (s = 0; s < q; ++s)
81539371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
81547c927364SMatthew G. Knepley         if (s < q) continue;
81557c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
81567c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
81577c927364SMatthew G. Knepley         ++q;
81587c927364SMatthew G. Knepley       }
81597c927364SMatthew G. Knepley     }
81609566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
81617c927364SMatthew G. Knepley   }
81627c927364SMatthew G. Knepley   numFPoints = q;
81637c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
81647c927364SMatthew G. Knepley     PetscInt fdof;
81657c927364SMatthew G. Knepley 
81669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
81677c927364SMatthew G. Knepley     if (!dof) continue;
81687c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
81699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
81707c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
81717c927364SMatthew G. Knepley     }
81727c927364SMatthew G. Knepley     numFIndices += dof;
81737c927364SMatthew G. Knepley   }
81747c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
81757c927364SMatthew G. Knepley 
81761dca8a05SBarry 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);
81771dca8a05SBarry 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);
81787c927364SMatthew G. Knepley   if (numFields) {
81794acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
81804acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
81814acb8e1eSToby Isaac 
81824acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
81839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
81849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
81857c927364SMatthew G. Knepley     }
81864acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
81879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
81889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
81894acb8e1eSToby Isaac     }
81904acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
81919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
81929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
81934acb8e1eSToby Isaac     }
81944acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
81959566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
81969566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
81977c927364SMatthew G. Knepley     }
81987c927364SMatthew G. Knepley   } else {
81994acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
82004acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
82014acb8e1eSToby Isaac 
82029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82044acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
82054acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
82064acb8e1eSToby Isaac 
82079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
82097c927364SMatthew G. Knepley     }
82104acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
82114acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
82124acb8e1eSToby Isaac 
82139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
82157c927364SMatthew G. Knepley     }
82169566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82179566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82187c927364SMatthew G. Knepley   }
82199566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
82209566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
82217c927364SMatthew G. Knepley   PetscFunctionReturn(0);
82227c927364SMatthew G. Knepley }
82237c927364SMatthew G. Knepley 
82247cd05799SMatthew G. Knepley /*@C
82257cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
82267cd05799SMatthew G. Knepley 
82277cd05799SMatthew G. Knepley   Input Parameter:
8228a1cb98faSBarry Smith . dm   - The `DMPLEX` object
82297cd05799SMatthew G. Knepley 
82307cd05799SMatthew G. Knepley   Output Parameter:
82317cd05799SMatthew G. Knepley . cellHeight - The height of a cell
82327cd05799SMatthew G. Knepley 
82337cd05799SMatthew G. Knepley   Level: developer
82347cd05799SMatthew G. Knepley 
8235a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`,  `DMPlexSetVTKCellHeight()`
82367cd05799SMatthew G. Knepley @*/
8237d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8238d71ae5a4SJacob Faibussowitsch {
8239552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8240552f7358SJed Brown 
8241552f7358SJed Brown   PetscFunctionBegin;
8242552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8243dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
8244552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
8245552f7358SJed Brown   PetscFunctionReturn(0);
8246552f7358SJed Brown }
8247552f7358SJed Brown 
82487cd05799SMatthew G. Knepley /*@C
82497cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
82507cd05799SMatthew G. Knepley 
82517cd05799SMatthew G. Knepley   Input Parameters:
8252a1cb98faSBarry Smith + dm   - The `DMPLEX` object
82537cd05799SMatthew G. Knepley - cellHeight - The height of a cell
82547cd05799SMatthew G. Knepley 
82557cd05799SMatthew G. Knepley   Level: developer
82567cd05799SMatthew G. Knepley 
8257a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
82587cd05799SMatthew G. Knepley @*/
8259d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8260d71ae5a4SJacob Faibussowitsch {
8261552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8262552f7358SJed Brown 
8263552f7358SJed Brown   PetscFunctionBegin;
8264552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8265552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
8266552f7358SJed Brown   PetscFunctionReturn(0);
8267552f7358SJed Brown }
8268552f7358SJed Brown 
8269e6139122SMatthew G. Knepley /*@
8270e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
8271e6139122SMatthew G. Knepley 
8272e6139122SMatthew G. Knepley   Input Parameter:
8273a1cb98faSBarry Smith . dm - The `DMPLEX` object
8274e6139122SMatthew G. Knepley 
8275e6139122SMatthew G. Knepley   Output Parameters:
82762a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
82772a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
8278e6139122SMatthew G. Knepley 
82792a9f31c0SMatthew G. Knepley   Level: advanced
8280e6139122SMatthew G. Knepley 
8281a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
8282e6139122SMatthew G. Knepley @*/
8283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8284d71ae5a4SJacob Faibussowitsch {
8285412e9a14SMatthew G. Knepley   DMLabel ctLabel;
8286e6139122SMatthew G. Knepley 
8287e6139122SMatthew G. Knepley   PetscFunctionBegin;
8288e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
82899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
82909566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8291695799ffSMatthew G. Knepley   // Reset label for fast lookup
8292695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
8293e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
8294e6139122SMatthew G. Knepley }
8295e6139122SMatthew G. Knepley 
8296d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8297d71ae5a4SJacob Faibussowitsch {
8298552f7358SJed Brown   PetscSection section, globalSection;
8299552f7358SJed Brown   PetscInt    *numbers, p;
8300552f7358SJed Brown 
8301552f7358SJed Brown   PetscFunctionBegin;
8302d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
83039566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
83049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
830548a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
83069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
83079566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
83089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8309552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
83109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8311ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8312ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8313552f7358SJed Brown   }
83149566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8315ef48cebcSMatthew G. Knepley   if (globalSize) {
8316ef48cebcSMatthew G. Knepley     PetscLayout layout;
83179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
83189566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
83199566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8320ef48cebcSMatthew G. Knepley   }
83219566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
83229566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
8323552f7358SJed Brown   PetscFunctionReturn(0);
8324552f7358SJed Brown }
8325552f7358SJed Brown 
8326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8327d71ae5a4SJacob Faibussowitsch {
8328412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8329552f7358SJed Brown 
8330552f7358SJed Brown   PetscFunctionBegin;
83319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
83329566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
83339566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
83349566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
833581ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8336552f7358SJed Brown }
833781ed3555SMatthew G. Knepley 
83388dab3259SMatthew G. Knepley /*@
83397cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
83407cd05799SMatthew G. Knepley 
83417cd05799SMatthew G. Knepley   Input Parameter:
8342a1cb98faSBarry Smith . dm   - The `DMPLEX` object
83437cd05799SMatthew G. Knepley 
83447cd05799SMatthew G. Knepley   Output Parameter:
83457cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
83467cd05799SMatthew G. Knepley 
83477cd05799SMatthew G. Knepley   Level: developer
83487cd05799SMatthew G. Knepley 
8349a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
83507cd05799SMatthew G. Knepley @*/
8351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8352d71ae5a4SJacob Faibussowitsch {
835381ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
835481ed3555SMatthew G. Knepley 
835581ed3555SMatthew G. Knepley   PetscFunctionBegin;
835681ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83579566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8358552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8359552f7358SJed Brown   PetscFunctionReturn(0);
8360552f7358SJed Brown }
8361552f7358SJed Brown 
8362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8363d71ae5a4SJacob Faibussowitsch {
8364412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
836581ed3555SMatthew G. Knepley 
836681ed3555SMatthew G. Knepley   PetscFunctionBegin;
836781ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
83699566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
837081ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
837181ed3555SMatthew G. Knepley }
837281ed3555SMatthew G. Knepley 
83738dab3259SMatthew G. Knepley /*@
83746aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
83757cd05799SMatthew G. Knepley 
83767cd05799SMatthew G. Knepley   Input Parameter:
8377a1cb98faSBarry Smith . dm   - The `DMPLEX` object
83787cd05799SMatthew G. Knepley 
83797cd05799SMatthew G. Knepley   Output Parameter:
83807cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
83817cd05799SMatthew G. Knepley 
83827cd05799SMatthew G. Knepley   Level: developer
83837cd05799SMatthew G. Knepley 
8384a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
83857cd05799SMatthew G. Knepley @*/
8386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8387d71ae5a4SJacob Faibussowitsch {
8388552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8389552f7358SJed Brown 
8390552f7358SJed Brown   PetscFunctionBegin;
8391552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83929566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8393552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8394552f7358SJed Brown   PetscFunctionReturn(0);
8395552f7358SJed Brown }
8396552f7358SJed Brown 
83978dab3259SMatthew G. Knepley /*@
8398966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8399966484cfSJed Brown 
8400966484cfSJed Brown   Collective on dm
84017cd05799SMatthew G. Knepley 
84027cd05799SMatthew G. Knepley   Input Parameter:
8403a1cb98faSBarry Smith . dm   - The `DMPLEX` object
84047cd05799SMatthew G. Knepley 
84057cd05799SMatthew G. Knepley   Output Parameter:
84067cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
84077cd05799SMatthew G. Knepley 
8408a1cb98faSBarry Smith   Level: developer
8409966484cfSJed Brown 
8410a1cb98faSBarry Smith   Notes:
8411a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8412966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8413966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8414966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8415966484cfSJed Brown 
8416966484cfSJed Brown   The partitioned mesh is
8417966484cfSJed Brown ```
8418966484cfSJed Brown  (2)--0--(3)--1--(4)    (1)--0--(2)
8419966484cfSJed Brown ```
8420966484cfSJed Brown   and its global numbering is
8421966484cfSJed Brown ```
8422966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8423966484cfSJed Brown ```
8424966484cfSJed Brown   Then the global numbering is provided as
8425966484cfSJed Brown ```
8426966484cfSJed Brown [0] Number of indices in set 5
8427966484cfSJed Brown [0] 0 0
8428966484cfSJed Brown [0] 1 1
8429966484cfSJed Brown [0] 2 3
8430966484cfSJed Brown [0] 3 4
8431966484cfSJed Brown [0] 4 -6
8432966484cfSJed Brown [1] Number of indices in set 3
8433966484cfSJed Brown [1] 0 2
8434966484cfSJed Brown [1] 1 5
8435966484cfSJed Brown [1] 2 6
8436966484cfSJed Brown ```
8437966484cfSJed Brown 
8438a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
84397cd05799SMatthew G. Knepley @*/
8440d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8441d71ae5a4SJacob Faibussowitsch {
8442ef48cebcSMatthew G. Knepley   IS        nums[4];
8443862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8444ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
84450c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8446ef48cebcSMatthew G. Knepley 
8447ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8448ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
84500c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
84519566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
84520c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8453862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8454862913ffSStefano Zampini     PetscInt end;
8455862913ffSStefano Zampini 
8456862913ffSStefano Zampini     depths[d] = depth - d;
84579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
84580c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8459862913ffSStefano Zampini   }
84600c15888dSMatthew G. Knepley   if (empty)
84610c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
84620c15888dSMatthew G. Knepley       depths[d] = -1;
84630c15888dSMatthew G. Knepley       starts[d] = -1;
84640c15888dSMatthew G. Knepley     }
84650c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
84661c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8467ad540459SPierre 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]);
84680c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8469ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8470ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8471ef48cebcSMatthew G. Knepley 
84729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
84739566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8474ef48cebcSMatthew G. Knepley     shift += gsize;
8475ef48cebcSMatthew G. Knepley   }
84769566063dSJacob Faibussowitsch   PetscCall(ISConcatenate(PetscObjectComm((PetscObject)dm), depth + 1, nums, globalPointNumbers));
84779566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
8478ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8479ef48cebcSMatthew G. Knepley }
8480ef48cebcSMatthew G. Knepley 
848108a22f4bSMatthew G. Knepley /*@
848208a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
848308a22f4bSMatthew G. Knepley 
848408a22f4bSMatthew G. Knepley   Input Parameter:
8485a1cb98faSBarry Smith . dm - The `DMPLEX` object
848608a22f4bSMatthew G. Knepley 
848708a22f4bSMatthew G. Knepley   Output Parameter:
848808a22f4bSMatthew G. Knepley . ranks - The rank field
848908a22f4bSMatthew G. Knepley 
8490a1cb98faSBarry Smith   Options Database Key:
849108a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
849208a22f4bSMatthew G. Knepley 
849308a22f4bSMatthew G. Knepley   Level: intermediate
849408a22f4bSMatthew G. Knepley 
8495a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`
849608a22f4bSMatthew G. Knepley @*/
8497d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8498d71ae5a4SJacob Faibussowitsch {
849908a22f4bSMatthew G. Knepley   DM             rdm;
850008a22f4bSMatthew G. Knepley   PetscFE        fe;
850108a22f4bSMatthew G. Knepley   PetscScalar   *r;
850208a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8503a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
850408a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8505a55f9a55SMatthew G. Knepley   PetscBool      simplex;
850608a22f4bSMatthew G. Knepley 
850708a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8508f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8509f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
85109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
85119566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
85129566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
85139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
85149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8515a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
85169566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
85179566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
85189566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
85199566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85209566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
85219566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
85229566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
85239566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
852408a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
852508a22f4bSMatthew G. Knepley     PetscScalar *lr;
852608a22f4bSMatthew G. Knepley 
85279566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
852871f09efeSPierre Jolivet     if (lr) *lr = rank;
852908a22f4bSMatthew G. Knepley   }
85309566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
85319566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
853208a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
853308a22f4bSMatthew G. Knepley }
853408a22f4bSMatthew G. Knepley 
8535ca8062c8SMatthew G. Knepley /*@
853618e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
853718e14f0cSMatthew G. Knepley 
853818e14f0cSMatthew G. Knepley   Input Parameters:
853918e14f0cSMatthew G. Knepley + dm    - The DMPlex
854018e14f0cSMatthew G. Knepley - label - The DMLabel
854118e14f0cSMatthew G. Knepley 
854218e14f0cSMatthew G. Knepley   Output Parameter:
854318e14f0cSMatthew G. Knepley . val - The label value field
854418e14f0cSMatthew G. Knepley 
854518e14f0cSMatthew G. Knepley   Options Database Keys:
854618e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
854718e14f0cSMatthew G. Knepley 
854818e14f0cSMatthew G. Knepley   Level: intermediate
854918e14f0cSMatthew G. Knepley 
8550a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMView()`
855118e14f0cSMatthew G. Knepley @*/
8552d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8553d71ae5a4SJacob Faibussowitsch {
855418e14f0cSMatthew G. Knepley   DM           rdm;
855518e14f0cSMatthew G. Knepley   PetscFE      fe;
855618e14f0cSMatthew G. Knepley   PetscScalar *v;
855718e14f0cSMatthew G. Knepley   PetscInt     dim, cStart, cEnd, c;
855818e14f0cSMatthew G. Knepley 
855918e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
856018e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
856118e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
856218e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
85639566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
85649566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
85659566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
85669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "label_value"));
85679566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
85689566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85699566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
85709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
85719566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
85729566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*val, "label_value"));
85739566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
857418e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
857518e14f0cSMatthew G. Knepley     PetscScalar *lv;
857618e14f0cSMatthew G. Knepley     PetscInt     cval;
857718e14f0cSMatthew G. Knepley 
85789566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
85799566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
858018e14f0cSMatthew G. Knepley     *lv = cval;
858118e14f0cSMatthew G. Knepley   }
85829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
85839566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
858418e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
858518e14f0cSMatthew G. Knepley }
858618e14f0cSMatthew G. Knepley 
858718e14f0cSMatthew G. Knepley /*@
8588ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8589ca8062c8SMatthew G. Knepley 
859069916449SMatthew G. Knepley   Input Parameter:
8591a1cb98faSBarry Smith . dm - The `DMPLEX` object
8592a1cb98faSBarry Smith 
8593a1cb98faSBarry Smith   Level: developer
8594ca8062c8SMatthew G. Knepley 
859595eb5ee5SVaclav Hapla   Notes:
859695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
859795eb5ee5SVaclav Hapla 
859895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8599ca8062c8SMatthew G. Knepley 
8600a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8601ca8062c8SMatthew G. Knepley @*/
8602d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8603d71ae5a4SJacob Faibussowitsch {
8604ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8605ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8606ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
860757beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
860857beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8609ca8062c8SMatthew G. Knepley 
8610ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8611ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86129566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
86139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
86149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8615ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
86169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8617ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
86189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
86199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8620ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
862142e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
862242e66dfaSMatthew G. Knepley       PetscInt  d;
862342e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
86249371c9d4SSatish Balay         if (cone[c] == cone[d]) {
86259371c9d4SSatish Balay           dup = PETSC_TRUE;
86269371c9d4SSatish Balay           break;
86279371c9d4SSatish Balay         }
862842e66dfaSMatthew G. Knepley       }
86299566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
86309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8631ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8632ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8633ca8062c8SMatthew G. Knepley       }
863442e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
863563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
863648a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
86379566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
863863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
863948a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
86409566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
864163a3b9bcSJacob 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]);
8642f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8643ca8062c8SMatthew G. Knepley       }
864442e66dfaSMatthew G. Knepley     }
86459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
86469371c9d4SSatish Balay     if (p != pp) {
86479371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
86489371c9d4SSatish Balay       continue;
86499371c9d4SSatish Balay     }
86509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
86519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8652ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
86539566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
86549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8655ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
86569566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
86579371c9d4SSatish Balay         if (cone[c] != pp) {
86589371c9d4SSatish Balay           c = 0;
86599371c9d4SSatish Balay           break;
86609371c9d4SSatish Balay         }
8661ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8662ca8062c8SMatthew G. Knepley       }
8663ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
866463a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
866548a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
86669566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
866763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
866848a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
86699566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
867063a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8671ca8062c8SMatthew G. Knepley       }
8672ca8062c8SMatthew G. Knepley     }
8673ca8062c8SMatthew G. Knepley   }
867457beb4faSStefano Zampini   if (storagecheck) {
86759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
86769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
867763a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
867857beb4faSStefano Zampini   }
8679ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8680ca8062c8SMatthew G. Knepley }
8681ca8062c8SMatthew G. Knepley 
8682412e9a14SMatthew G. Knepley /*
8683412e9a14SMatthew 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.
8684412e9a14SMatthew G. Knepley */
8685d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8686d71ae5a4SJacob Faibussowitsch {
8687412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8688412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8689412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8690412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8691412e9a14SMatthew G. Knepley 
8692412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8693412e9a14SMatthew G. Knepley   *unsplit = 0;
8694412e9a14SMatthew G. Knepley   switch (ct) {
8695d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
8696d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
8697d71ae5a4SJacob Faibussowitsch     break;
8698412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
86999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8701412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87029566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8703412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8704412e9a14SMatthew G. Knepley     }
8705412e9a14SMatthew G. Knepley     break;
8706412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
8707412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
87089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8710412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
87129566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8713412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
87149566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8715412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8716412e9a14SMatthew G. Knepley           PetscInt p;
87179371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
87189371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
8719412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
8720412e9a14SMatthew G. Knepley         }
8721412e9a14SMatthew G. Knepley       }
8722412e9a14SMatthew G. Knepley     }
8723412e9a14SMatthew G. Knepley     break;
8724d71ae5a4SJacob Faibussowitsch   default:
8725d71ae5a4SJacob Faibussowitsch     break;
8726412e9a14SMatthew G. Knepley   }
8727412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
87289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8729412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8730412e9a14SMatthew G. Knepley   }
8731412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8732412e9a14SMatthew G. Knepley }
8733412e9a14SMatthew G. Knepley 
8734ca8062c8SMatthew G. Knepley /*@
8735ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8736ca8062c8SMatthew G. Knepley 
8737ca8062c8SMatthew G. Knepley   Input Parameters:
8738a1cb98faSBarry Smith + dm - The `DMPLEX` object
873958723a97SMatthew G. Knepley - cellHeight - Normally 0
8740ca8062c8SMatthew G. Knepley 
8741a1cb98faSBarry Smith   Level: developer
8742a1cb98faSBarry Smith 
874395eb5ee5SVaclav Hapla   Notes:
874495eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
874525c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8746ca8062c8SMatthew G. Knepley 
874795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
874895eb5ee5SVaclav Hapla 
8749a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8750ca8062c8SMatthew G. Knepley @*/
8751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8752d71ae5a4SJacob Faibussowitsch {
8753412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8754412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8755412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8756ca8062c8SMatthew G. Knepley 
8757ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8758ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87599566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
87609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
87619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8762412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8763412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8764412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
876558723a97SMatthew G. Knepley 
87669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
876763a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8768412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8769412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
87709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
877163a3b9bcSJacob 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));
8772412e9a14SMatthew G. Knepley     }
87739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
877458723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
877558723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8776412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
877758723a97SMatthew G. Knepley     }
87789566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8779412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8780412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8781412e9a14SMatthew G. Knepley       PetscInt unsplit;
878242363296SMatthew G. Knepley 
87839566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8784412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
878542363296SMatthew G. Knepley     }
878663a3b9bcSJacob 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));
878742363296SMatthew G. Knepley   }
8788ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8789ca8062c8SMatthew G. Knepley }
87909bf0dad6SMatthew G. Knepley 
87919bf0dad6SMatthew G. Knepley /*@
87929bf0dad6SMatthew 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
87939bf0dad6SMatthew G. Knepley 
8794a1cb98faSBarry Smith   Collective on dm
8795899ea2b8SJacob Faibussowitsch 
87969bf0dad6SMatthew G. Knepley   Input Parameters:
8797a1cb98faSBarry Smith + dm - The `DMPLEX` object
87989bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
87999bf0dad6SMatthew G. Knepley 
8800a1cb98faSBarry Smith   Level: developer
8801a1cb98faSBarry Smith 
880245da879fSVaclav Hapla   Notes:
880345da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
880445da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
880545da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
880645da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
88079bf0dad6SMatthew G. Knepley 
8808a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
880995eb5ee5SVaclav Hapla 
8810a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
88119bf0dad6SMatthew G. Knepley @*/
8812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
8813d71ae5a4SJacob Faibussowitsch {
8814ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8815899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
88169bf0dad6SMatthew G. Knepley 
88179bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
88189bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88198f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
882045da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
88218f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
88228f6815adSVaclav Hapla     PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported");
88238f6815adSVaclav Hapla     PetscFunctionReturn(0);
8824899ea2b8SJacob Faibussowitsch   }
8825899ea2b8SJacob Faibussowitsch 
88269566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
88279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
88289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8829ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
88309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
88313554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8832412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
8833412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8834ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8835412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8836412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
88379bf0dad6SMatthew G. Knepley 
88389566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
88399566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8840412e9a14SMatthew G. Knepley       if (unsplit) continue;
88419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
88429566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
88439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
88449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
88459bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
88469bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
88479bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
88489bf0dad6SMatthew G. Knepley       }
88499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
885063a3b9bcSJacob 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);
88519bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8852d4961f80SStefano Zampini         DMPolytopeType fct;
88539bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
88549bf0dad6SMatthew G. Knepley 
88559566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
88569566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
88579bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
88589bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
88599bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
88609bf0dad6SMatthew G. Knepley         }
886163a3b9bcSJacob 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]);
88629bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8863b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
8864b5a892a1SMatthew G. Knepley             PetscInt v1;
8865b5a892a1SMatthew G. Knepley 
88669566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
886763a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
88689566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
886963a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
88709566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
887163a3b9bcSJacob 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]);
8872b5a892a1SMatthew G. Knepley           }
88739bf0dad6SMatthew G. Knepley         }
88749566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8875412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
88769bf0dad6SMatthew G. Knepley       }
88779566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
88789566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
88799bf0dad6SMatthew G. Knepley     }
88803554e41dSMatthew G. Knepley   }
8881552f7358SJed Brown   PetscFunctionReturn(0);
8882552f7358SJed Brown }
88833913d7c8SMatthew G. Knepley 
8884bb6a34a8SMatthew G. Knepley /*@
8885bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8886bb6a34a8SMatthew G. Knepley 
8887bb6a34a8SMatthew G. Knepley   Input Parameter:
8888a1cb98faSBarry Smith . dm - The `DMPLEX` object
8889a1cb98faSBarry Smith 
8890a1cb98faSBarry Smith   Level: developer
8891bb6a34a8SMatthew G. Knepley 
889295eb5ee5SVaclav Hapla   Notes:
889395eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
889495eb5ee5SVaclav Hapla 
889595eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8896bb6a34a8SMatthew G. Knepley 
8897a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8898bb6a34a8SMatthew G. Knepley @*/
8899d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
8900d71ae5a4SJacob Faibussowitsch {
8901a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8902bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8903bb6a34a8SMatthew G. Knepley   PetscReal vol;
890451a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8905bb6a34a8SMatthew G. Knepley 
8906bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
89079566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
89089566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
890951a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
89109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8911bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
89129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8913a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
89149566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8915dd4c3f67SMatthew G. Knepley   if (!coordinates) PetscFunctionReturn(0);
8916412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8917412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8918412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8919412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8920412e9a14SMatthew G. Knepley 
89219566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8922412e9a14SMatthew G. Knepley     switch (ct) {
8923412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8924412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8925d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8926d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
8927d71ae5a4SJacob Faibussowitsch       break;
8928d71ae5a4SJacob Faibussowitsch     default:
8929d71ae5a4SJacob Faibussowitsch       break;
8930412e9a14SMatthew G. Knepley     }
8931412e9a14SMatthew G. Knepley     switch (ct) {
8932412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
8933412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8934412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8935d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
8936d71ae5a4SJacob Faibussowitsch       continue;
8937d71ae5a4SJacob Faibussowitsch     default:
8938d71ae5a4SJacob Faibussowitsch       break;
8939412e9a14SMatthew G. Knepley     }
89409566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8941412e9a14SMatthew G. Knepley     if (unsplit) continue;
89429566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
89431dca8a05SBarry 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);
894463a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
89456858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
89466858538eSMatthew G. Knepley     if (depth > 1) {
89479566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
89481dca8a05SBarry 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);
894963a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
8950bb6a34a8SMatthew G. Knepley     }
8951bb6a34a8SMatthew G. Knepley   }
8952bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8953bb6a34a8SMatthew G. Knepley }
8954bb6a34a8SMatthew G. Knepley 
895503da9461SVaclav Hapla /*@
89567726db96SVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex.
89577726db96SVaclav Hapla 
8958a1cb98faSBarry Smith   Collective on dm
895903da9461SVaclav Hapla 
896003da9461SVaclav Hapla   Input Parameters:
8961a1cb98faSBarry Smith + dm - The `DMPLEX` object
8962a1cb98faSBarry Smith . pointSF - The `PetscSF`, or NULL for `PointSF` attached to `DM`
8963a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
8964a1cb98faSBarry Smith 
8965a1cb98faSBarry Smith   Level: developer
896603da9461SVaclav Hapla 
8967e83a0d2dSVaclav Hapla   Notes:
8968e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
896903da9461SVaclav Hapla 
8970a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
897195eb5ee5SVaclav Hapla 
8972d7d32a9aSMatthew G. Knepley   Extra roots can come from priodic cuts, where additional points appear on the boundary
8973d7d32a9aSMatthew G. Knepley 
8974a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
897503da9461SVaclav Hapla @*/
8976d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
8977d71ae5a4SJacob Faibussowitsch {
89787726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
89797726db96SVaclav Hapla   const PetscInt    *locals;
89807726db96SVaclav Hapla   const PetscSFNode *remotes;
8981f0cfc026SVaclav Hapla   PetscBool          distributed;
89827726db96SVaclav Hapla   MPI_Comm           comm;
89837726db96SVaclav Hapla   PetscMPIInt        rank;
898403da9461SVaclav Hapla 
898503da9461SVaclav Hapla   PetscFunctionBegin;
898603da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89877726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
89887726db96SVaclav Hapla   else pointSF = dm->sf;
89897726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
89907726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
89917726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
89927726db96SVaclav Hapla   {
89937726db96SVaclav Hapla     PetscMPIInt mpiFlag;
89947726db96SVaclav Hapla 
89957726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
89967726db96SVaclav 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);
89977726db96SVaclav Hapla   }
89987726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
89999566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
90007726db96SVaclav Hapla   if (!distributed) {
90017726db96SVaclav 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);
90028918e3e2SVaclav Hapla     PetscFunctionReturn(0);
90038918e3e2SVaclav Hapla   }
90047726db96SVaclav 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);
90057726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
900603da9461SVaclav Hapla 
90077726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
90087726db96SVaclav Hapla   {
90097726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
90107726db96SVaclav Hapla 
90117726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
90127726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9013d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
90147726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
90157726db96SVaclav Hapla   }
90167726db96SVaclav Hapla 
90177726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
90187726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
90197726db96SVaclav 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);
90207726db96SVaclav Hapla   }
90217726db96SVaclav Hapla 
90227726db96SVaclav Hapla   /* Check there are no cells in interface */
90237726db96SVaclav Hapla   if (!overlap) {
90247726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
90257726db96SVaclav Hapla 
90269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9028f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
90297726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9030f5869d18SMatthew G. Knepley 
90317726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
90327726db96SVaclav Hapla     }
903303da9461SVaclav Hapla   }
9034ece87651SVaclav Hapla 
90357726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
90367726db96SVaclav Hapla   {
90377726db96SVaclav Hapla     const PetscInt *rootdegree;
90387726db96SVaclav Hapla 
90397726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
90407726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9041f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
90427726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9043f5869d18SMatthew G. Knepley       const PetscInt *cone;
9044f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9045f5869d18SMatthew G. Knepley 
90469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
90479566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9048f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9049f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
90507726db96SVaclav Hapla           if (locals) {
90519566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
90527726db96SVaclav Hapla           } else {
90537726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
90547726db96SVaclav Hapla           }
905563a3b9bcSJacob 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]);
9056f5869d18SMatthew G. Knepley         }
9057f5869d18SMatthew G. Knepley       }
9058ece87651SVaclav Hapla     }
90597726db96SVaclav Hapla   }
906003da9461SVaclav Hapla   PetscFunctionReturn(0);
906103da9461SVaclav Hapla }
906203da9461SVaclav Hapla 
90637f9d8d6cSVaclav Hapla /*@
90647f9d8d6cSVaclav Hapla   DMPlexCheck - Perform various checks of Plex sanity
90657f9d8d6cSVaclav Hapla 
90667f9d8d6cSVaclav Hapla   Input Parameter:
9067a1cb98faSBarry Smith . dm - The `DMPLEX` object
9068a1cb98faSBarry Smith 
9069a1cb98faSBarry Smith   Level: developer
90707f9d8d6cSVaclav Hapla 
90717f9d8d6cSVaclav Hapla   Notes:
90727f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
90737f9d8d6cSVaclav Hapla 
90747f9d8d6cSVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
90757f9d8d6cSVaclav Hapla 
90767f9d8d6cSVaclav Hapla   Currently does not include DMPlexCheckCellShape().
90777f9d8d6cSVaclav Hapla 
9078a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, DMCreate(), DMSetFromOptions()
90797f9d8d6cSVaclav Hapla @*/
9080d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9081d71ae5a4SJacob Faibussowitsch {
90827f9d8d6cSVaclav Hapla   PetscInt cellHeight;
90837f9d8d6cSVaclav Hapla 
9084b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
90857f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90869566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
90879566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
90889566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
90899566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9090d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
90919566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
9092b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9093b5a892a1SMatthew G. Knepley }
9094b5a892a1SMatthew G. Knepley 
90959371c9d4SSatish Balay typedef struct cell_stats {
9096068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9097068a5610SStefano Zampini   PetscInt  count;
9098068a5610SStefano Zampini } cell_stats_t;
9099068a5610SStefano Zampini 
9100d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9101d71ae5a4SJacob Faibussowitsch {
9102068a5610SStefano Zampini   PetscInt i, N = *len;
9103068a5610SStefano Zampini 
9104068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9105068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9106068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9107068a5610SStefano Zampini 
9108068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9109068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9110068a5610SStefano Zampini     B->sum += A->sum;
9111068a5610SStefano Zampini     B->squaresum += A->squaresum;
9112068a5610SStefano Zampini     B->count += A->count;
9113068a5610SStefano Zampini   }
9114068a5610SStefano Zampini }
9115068a5610SStefano Zampini 
9116068a5610SStefano Zampini /*@
911743fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9118068a5610SStefano Zampini 
91198261a58bSMatthew G. Knepley   Collective on dm
91208261a58bSMatthew G. Knepley 
9121068a5610SStefano Zampini   Input Parameters:
9122a1cb98faSBarry Smith + dm        - The `DMPLEX` object
912343fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
9124a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9125a1cb98faSBarry Smith 
9126a1cb98faSBarry Smith   Level: developer
9127068a5610SStefano Zampini 
912895eb5ee5SVaclav Hapla   Notes:
912995eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
913095eb5ee5SVaclav Hapla 
9131a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9132068a5610SStefano Zampini 
9133a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9134068a5610SStefano Zampini @*/
9135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9136d71ae5a4SJacob Faibussowitsch {
9137068a5610SStefano Zampini   DM           dmCoarse;
913843fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
913943fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
914043fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
914143fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9142412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
914343fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9144068a5610SStefano Zampini 
9145068a5610SStefano Zampini   PetscFunctionBegin;
9146068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9147068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9148068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9149068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9150068a5610SStefano Zampini   stats.count                 = 0;
9151068a5610SStefano Zampini 
91529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
91539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
91549566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
91559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
91569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
91579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9158412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9159068a5610SStefano Zampini     PetscInt  i;
9160068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9161068a5610SStefano Zampini 
91629566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
916363a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
916443fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9165068a5610SStefano Zampini       frobJ += J[i] * J[i];
9166068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9167068a5610SStefano Zampini     }
9168068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9169068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9170068a5610SStefano Zampini 
9171068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9172068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9173068a5610SStefano Zampini     stats.sum += cond;
9174068a5610SStefano Zampini     stats.squaresum += cond2;
9175068a5610SStefano Zampini     stats.count++;
91768261a58bSMatthew G. Knepley     if (output && cond > limit) {
917743fa8764SMatthew G. Knepley       PetscSection coordSection;
917843fa8764SMatthew G. Knepley       Vec          coordsLocal;
917943fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
918043fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
918143fa8764SMatthew G. Knepley 
91829566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
91839566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
91849566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
918563a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
918643fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
918763a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
918843fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
91899566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
91909566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
919143fa8764SMatthew G. Knepley         }
91929566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
919343fa8764SMatthew G. Knepley       }
91949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
919543fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
919643fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
919743fa8764SMatthew G. Knepley 
919843fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
919943fa8764SMatthew G. Knepley           PetscReal len;
920043fa8764SMatthew G. Knepley 
92019566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
920263a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
920343fa8764SMatthew G. Knepley         }
920443fa8764SMatthew G. Knepley       }
92059566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
92069566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
920743fa8764SMatthew G. Knepley     }
9208068a5610SStefano Zampini   }
92099566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9210068a5610SStefano Zampini 
9211068a5610SStefano Zampini   if (size > 1) {
9212068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9213068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9214068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9215068a5610SStefano Zampini     MPI_Op       statReduce;
9216068a5610SStefano Zampini 
92179566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
92189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
92199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
92209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
92219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
92229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9223068a5610SStefano Zampini   } else {
92249566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9225068a5610SStefano Zampini   }
9226dd400576SPatrick Sanan   if (rank == 0) {
9227068a5610SStefano Zampini     count = globalStats.count;
9228068a5610SStefano Zampini     min   = globalStats.min;
9229068a5610SStefano Zampini     max   = globalStats.max;
9230068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9231068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9232068a5610SStefano Zampini   }
9233068a5610SStefano Zampini 
923448a46eb9SPierre 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));
92359566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9236068a5610SStefano Zampini 
92379566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9238068a5610SStefano Zampini   if (dmCoarse) {
9239068a5610SStefano Zampini     PetscBool isplex;
9240068a5610SStefano Zampini 
92419566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
92421baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9243068a5610SStefano Zampini   }
9244068a5610SStefano Zampini   PetscFunctionReturn(0);
9245068a5610SStefano Zampini }
9246068a5610SStefano Zampini 
9247f108dbd7SJacob Faibussowitsch /*@
9248f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9249f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9250f108dbd7SJacob Faibussowitsch 
92516ed19f2fSJacob Faibussowitsch   Collective on dm
9252f108dbd7SJacob Faibussowitsch 
9253f108dbd7SJacob Faibussowitsch   Input Parameters:
9254a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9255a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9256f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9257f108dbd7SJacob Faibussowitsch 
9258f108dbd7SJacob Faibussowitsch   Output Parameters:
9259f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
9260a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9261f108dbd7SJacob Faibussowitsch 
9262f108dbd7SJacob Faibussowitsch   Options Database Keys:
9263a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9264f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
9265f108dbd7SJacob Faibussowitsch 
9266a1cb98faSBarry Smith   Level: intermediate
9267a1cb98faSBarry Smith 
9268f108dbd7SJacob Faibussowitsch   Notes:
9269f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
9270f108dbd7SJacob Faibussowitsch 
9271a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9272f108dbd7SJacob Faibussowitsch 
9273f108dbd7SJacob 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
9274f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9275f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9276f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9277f108dbd7SJacob Faibussowitsch 
9278f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9279f108dbd7SJacob Faibussowitsch 
9280a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9281f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9282f108dbd7SJacob Faibussowitsch 
9283f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9284f108dbd7SJacob Faibussowitsch 
9285a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9286f108dbd7SJacob Faibussowitsch @*/
9287d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9288d71ae5a4SJacob Faibussowitsch {
92896ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
92906ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
92916ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9292f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
92936ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9294f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9295f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9296f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9297f108dbd7SJacob Faibussowitsch   IS                     glob;
9298f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9299f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9300f108dbd7SJacob Faibussowitsch 
9301f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9302f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9303ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
9304f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
93056bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
93069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
93079566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
930863a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
93096ed19f2fSJacob Faibussowitsch   {
93106ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
93116ed19f2fSJacob Faibussowitsch 
93129566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9313f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9314f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9315f108dbd7SJacob Faibussowitsch 
93169566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
931798921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9318f108dbd7SJacob Faibussowitsch     }
93196ed19f2fSJacob Faibussowitsch   }
9320f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
9321f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
93229566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
93239566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
93249371c9d4SSatish Balay   } else {
93259371c9d4SSatish Balay     *OrthQualLabel = NULL;
93269371c9d4SSatish Balay   }
93279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
93289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
93299566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
93309566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
93319566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
93329566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
93339566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
93349566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
93359566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
93369566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
93379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
93389566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
93399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
93409566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
93419566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
93429566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
93439566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
93449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
93456ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
93466ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9347f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9348f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9349898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9350f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9351f108dbd7SJacob Faibussowitsch 
93526ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9353f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9354f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
93559566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
93569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9357f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
93589566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
93596ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
93606ed19f2fSJacob Faibussowitsch       PetscInt         i;
93616ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9362f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9363f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9364f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9365f108dbd7SJacob Faibussowitsch 
9366f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9367f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
93689566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9369f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
93706ed19f2fSJacob Faibussowitsch       {
93716ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
93726ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
93736ed19f2fSJacob Faibussowitsch 
93749566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
93759566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
93769566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
93776ed19f2fSJacob Faibussowitsch       }
9378f108dbd7SJacob Faibussowitsch 
9379f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9380f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9381f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9382f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9383f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9384addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9385addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9386addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9387f108dbd7SJacob Faibussowitsch       }
9388addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9389addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9390addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9391f108dbd7SJacob Faibussowitsch 
9392f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9393f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9394f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9395f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9396f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9397f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9398f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9399f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9400f108dbd7SJacob Faibussowitsch       }
9401ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9402ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9403f108dbd7SJacob Faibussowitsch     }
94049566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
94059566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9406f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
94076ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9408f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
94099566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9410f108dbd7SJacob Faibussowitsch     }
9411f108dbd7SJacob Faibussowitsch   }
94129566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
94139566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
94149566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
94159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
94169566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
94179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9418f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
94199566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9420f108dbd7SJacob Faibussowitsch   }
94219566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
94229566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
94239566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9424f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9425f108dbd7SJacob Faibussowitsch }
9426f108dbd7SJacob Faibussowitsch 
9427d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
94281eb70e55SToby Isaac  * interpolator construction */
9429d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9430d71ae5a4SJacob Faibussowitsch {
94311eb70e55SToby Isaac   PetscSection section, newSection, gsection;
94321eb70e55SToby Isaac   PetscSF      sf;
94331eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
94341eb70e55SToby Isaac 
94351eb70e55SToby Isaac   PetscFunctionBegin;
94361eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94371eb70e55SToby Isaac   PetscValidPointer(odm, 2);
94389566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
94399566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
94409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
94411eb70e55SToby Isaac   if (!ghasConstraints) {
94429566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
94431eb70e55SToby Isaac     *odm = dm;
94441eb70e55SToby Isaac     PetscFunctionReturn(0);
94451eb70e55SToby Isaac   }
94469566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
94479566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
94489566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
94499566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
94509566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
94519566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
94529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
94531eb70e55SToby Isaac   PetscFunctionReturn(0);
94541eb70e55SToby Isaac }
94551eb70e55SToby Isaac 
9456d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9457d71ae5a4SJacob Faibussowitsch {
94581eb70e55SToby Isaac   DM        dmco, dmfo;
94591eb70e55SToby Isaac   Mat       interpo;
94601eb70e55SToby Isaac   Vec       rscale;
94611eb70e55SToby Isaac   Vec       cglobalo, clocal;
94621eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
94631eb70e55SToby Isaac   PetscBool regular;
94641eb70e55SToby Isaac 
94651eb70e55SToby Isaac   PetscFunctionBegin;
94669566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
94679566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
94689566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
94699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
94709566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
94719566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
94729566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
94739566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
94749566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
94759566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
94769566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
94779566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
94789566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
94799566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
94809566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
94819566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
94829566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
94839566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
94849566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
94859566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
94869566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
94879566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
94889566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
94899566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
94901eb70e55SToby Isaac   *shift = fglobal;
94919566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
94929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
94939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
94949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
94959566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
94969566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
94979566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
94989566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
94991eb70e55SToby Isaac   PetscFunctionReturn(0);
95001eb70e55SToby Isaac }
95011eb70e55SToby Isaac 
9502d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9503d71ae5a4SJacob Faibussowitsch {
95041eb70e55SToby Isaac   PetscObject shifto;
95051eb70e55SToby Isaac   Vec         shift;
95061eb70e55SToby Isaac 
95071eb70e55SToby Isaac   PetscFunctionBegin;
95081eb70e55SToby Isaac   if (!interp) {
95091eb70e55SToby Isaac     Vec rscale;
95101eb70e55SToby Isaac 
95119566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
95129566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
95131eb70e55SToby Isaac   } else {
95149566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
95151eb70e55SToby Isaac   }
95169566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
95171eb70e55SToby Isaac   if (!shifto) {
95189566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
95199566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
95201eb70e55SToby Isaac     shifto = (PetscObject)shift;
95219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
95221eb70e55SToby Isaac   }
95231eb70e55SToby Isaac   shift = (Vec)shifto;
95249566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
95259566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
95269566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
95271eb70e55SToby Isaac   PetscFunctionReturn(0);
95281eb70e55SToby Isaac }
95291eb70e55SToby Isaac 
9530bceba477SMatthew G. Knepley /* Pointwise interpolation
9531bceba477SMatthew G. Knepley      Just code FEM for now
9532bceba477SMatthew G. Knepley      u^f = I u^c
95334ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
95344ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
95354ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9536bceba477SMatthew G. Knepley */
9537d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9538d71ae5a4SJacob Faibussowitsch {
9539bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9540bceba477SMatthew G. Knepley   PetscInt     m, n;
9541a063dac3SMatthew G. Knepley   void        *ctx;
954268132eb9SMatthew G. Knepley   DM           cdm;
9543cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9544bceba477SMatthew G. Knepley 
9545bceba477SMatthew G. Knepley   PetscFunctionBegin;
95469566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
95479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
95489566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
95499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
955068132eb9SMatthew G. Knepley 
95519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
95529566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
95539566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
95549566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
95559566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
955668132eb9SMatthew G. Knepley 
95579566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
95589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
95599566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
95609566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
95619566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
95624db47ee9SStefano Zampini   if (scaling) {
95635d1c2e58SMatthew G. Knepley     /* Use naive scaling */
95649566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
95654db47ee9SStefano Zampini   }
9566a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9567a063dac3SMatthew G. Knepley }
9568bceba477SMatthew G. Knepley 
9569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9570d71ae5a4SJacob Faibussowitsch {
95716dbf9973SLawrence Mitchell   VecScatter ctx;
957290748bafSMatthew G. Knepley 
9573a063dac3SMatthew G. Knepley   PetscFunctionBegin;
95749566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
95759566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
95769566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
9577bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9578bceba477SMatthew G. Knepley }
9579bceba477SMatthew G. Knepley 
9580d71ae5a4SJacob 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[])
9581d71ae5a4SJacob Faibussowitsch {
958200635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
958300635df3SMatthew G. Knepley   PetscInt       c;
958400635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
95853e9753d6SMatthew G. Knepley }
95863e9753d6SMatthew G. Knepley 
9587d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9588d71ae5a4SJacob Faibussowitsch {
9589b4937a87SMatthew G. Knepley   DM           dmc;
9590b4937a87SMatthew G. Knepley   PetscDS      ds;
9591b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9592b4937a87SMatthew G. Knepley   IS           cellIS;
9593b4937a87SMatthew G. Knepley   PetscFormKey key;
9594b4937a87SMatthew G. Knepley   PetscInt     depth;
9595b4937a87SMatthew G. Knepley 
9596b4937a87SMatthew G. Knepley   PetscFunctionBegin;
95979566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
95989566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
95999566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
96009566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
96019566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
96029566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
96039566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
96049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
96059566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
96069566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
96079566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9608b4937a87SMatthew G. Knepley   key.label = NULL;
9609b4937a87SMatthew G. Knepley   key.value = 0;
9610b4937a87SMatthew G. Knepley   key.field = 0;
9611b4937a87SMatthew G. Knepley   key.part  = 0;
96129566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
96139566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
96149566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
96159566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
96169566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
96179566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
96189566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
96199566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
9620b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9621b4937a87SMatthew G. Knepley }
9622b4937a87SMatthew G. Knepley 
9623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9624d71ae5a4SJacob Faibussowitsch {
9625bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9626bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9627bd041c0cSMatthew G. Knepley   void        *ctx;
9628bd041c0cSMatthew G. Knepley   DM           cdm;
9629bd041c0cSMatthew G. Knepley   PetscBool    regular;
9630bd041c0cSMatthew G. Knepley 
9631bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
96323e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
96333e9753d6SMatthew G. Knepley     DM            dmc;
96343e9753d6SMatthew G. Knepley     PetscDS       ds;
9635b4937a87SMatthew G. Knepley     PetscWeakForm wf;
96363e9753d6SMatthew G. Knepley     Vec           u;
96373e9753d6SMatthew G. Knepley     IS            cellIS;
963806ad1575SMatthew G. Knepley     PetscFormKey  key;
96393e9753d6SMatthew G. Knepley     PetscInt      depth;
96403e9753d6SMatthew G. Knepley 
96419566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
96429566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
96439566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
96449566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
96459566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
96469566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
96479566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
96488d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
96499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
96509566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
96519566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
96526528b96dSMatthew G. Knepley     key.label = NULL;
96536528b96dSMatthew G. Knepley     key.value = 0;
96546528b96dSMatthew G. Knepley     key.field = 0;
965506ad1575SMatthew G. Knepley     key.part  = 0;
96569566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
96579566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
96588d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
96599566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
96603e9753d6SMatthew G. Knepley   } else {
96619566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
96629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
96639566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
96649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9665bd041c0cSMatthew G. Knepley 
96669566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
96679566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
96689566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
96699566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9670bd041c0cSMatthew G. Knepley 
96719566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
96729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
96739566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
96749566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
96753e9753d6SMatthew G. Knepley   }
96769566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9677bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9678bd041c0cSMatthew G. Knepley }
9679bd041c0cSMatthew G. Knepley 
96800aef6b92SMatthew G. Knepley /*@
96810aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
96820aef6b92SMatthew G. Knepley 
96830aef6b92SMatthew G. Knepley   Input Parameter:
9684a1cb98faSBarry Smith . dm - The `DMPLEX` object
96850aef6b92SMatthew G. Knepley 
96860aef6b92SMatthew G. Knepley   Output Parameter:
96870aef6b92SMatthew G. Knepley . regular - The flag
96880aef6b92SMatthew G. Knepley 
96890aef6b92SMatthew G. Knepley   Level: intermediate
96900aef6b92SMatthew G. Knepley 
9691a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
96920aef6b92SMatthew G. Knepley @*/
9693d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
9694d71ae5a4SJacob Faibussowitsch {
96950aef6b92SMatthew G. Knepley   PetscFunctionBegin;
96960aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9697dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
96980aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
96990aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
97000aef6b92SMatthew G. Knepley }
97010aef6b92SMatthew G. Knepley 
97020aef6b92SMatthew G. Knepley /*@
97030aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
97040aef6b92SMatthew G. Knepley 
97050aef6b92SMatthew G. Knepley   Input Parameters:
9706a1cb98faSBarry Smith + dm - The `DMPLEX` object
97070aef6b92SMatthew G. Knepley - regular - The flag
97080aef6b92SMatthew G. Knepley 
97090aef6b92SMatthew G. Knepley   Level: intermediate
97100aef6b92SMatthew G. Knepley 
9711a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
97120aef6b92SMatthew G. Knepley @*/
9713d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
9714d71ae5a4SJacob Faibussowitsch {
97150aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97160aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97170aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
97180aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
97190aef6b92SMatthew G. Knepley }
97200aef6b92SMatthew G. Knepley 
9721a68b90caSToby Isaac /*@
9722f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9723a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
9724a68b90caSToby Isaac 
9725a1cb98faSBarry Smith   Not Collective
9726a68b90caSToby Isaac 
9727f899ff85SJose E. Roman   Input Parameter:
9728a1cb98faSBarry Smith . dm - The `DMPLEX` object
9729a68b90caSToby Isaac 
9730a68b90caSToby Isaac   Output Parameters:
9731a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9732a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9733a68b90caSToby Isaac 
9734a68b90caSToby Isaac   Level: intermediate
9735a68b90caSToby Isaac 
9736a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
9737a68b90caSToby Isaac @*/
9738d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9739d71ae5a4SJacob Faibussowitsch {
9740a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9741a68b90caSToby Isaac 
9742a68b90caSToby Isaac   PetscFunctionBegin;
9743a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97449566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9745a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9746a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9747a68b90caSToby Isaac   PetscFunctionReturn(0);
9748a68b90caSToby Isaac }
9749a68b90caSToby Isaac 
9750a68b90caSToby Isaac /*@
9751f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9752f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9753a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9754a68b90caSToby Isaac 
9755a1cb98faSBarry Smith   Collective on dm
9756a68b90caSToby Isaac 
9757a68b90caSToby Isaac   Input Parameters:
9758a1cb98faSBarry Smith + dm - The `DMPLEX` object
9759a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
9760a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9761a1cb98faSBarry Smith - anchorIS - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9762a68b90caSToby Isaac 
9763a68b90caSToby Isaac   Level: intermediate
9764a68b90caSToby Isaac 
9765a1cb98faSBarry Smith   Notes:
9766a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
9767a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
9768a1cb98faSBarry Smith 
9769a1cb98faSBarry Smith   The reference counts of anchorSection and anchorIS are incremented.
9770a1cb98faSBarry Smith 
9771a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9772a68b90caSToby Isaac @*/
9773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9774d71ae5a4SJacob Faibussowitsch {
9775a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
9776e228b242SToby Isaac   PetscMPIInt result;
9777a68b90caSToby Isaac 
9778a68b90caSToby Isaac   PetscFunctionBegin;
9779a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9780e228b242SToby Isaac   if (anchorSection) {
9781e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
97829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
97831dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
9784e228b242SToby Isaac   }
9785e228b242SToby Isaac   if (anchorIS) {
9786e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
97879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
97881dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
9789e228b242SToby Isaac   }
9790a68b90caSToby Isaac 
97919566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
97929566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9793a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9794a68b90caSToby Isaac 
97959566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
97969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9797a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9798a68b90caSToby Isaac 
9799cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9800a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
9801a68b90caSToby Isaac     const PetscInt *anchors;
9802a68b90caSToby Isaac 
98039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
98049566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
98059566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
9806a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9807a68b90caSToby Isaac       PetscInt p;
9808a68b90caSToby Isaac 
9809a68b90caSToby Isaac       p = anchors[a];
9810a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9811a68b90caSToby Isaac         PetscInt dof;
9812a68b90caSToby Isaac 
98139566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9814a68b90caSToby Isaac         if (dof) {
98159566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
981663a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
9817a68b90caSToby Isaac         }
9818a68b90caSToby Isaac       }
9819a68b90caSToby Isaac     }
98209566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
9821a68b90caSToby Isaac   }
9822f7c74593SToby Isaac   /* reset the generic constraints */
98239566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
9824a68b90caSToby Isaac   PetscFunctionReturn(0);
9825a68b90caSToby Isaac }
9826a68b90caSToby Isaac 
9827d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9828d71ae5a4SJacob Faibussowitsch {
9829f7c74593SToby Isaac   PetscSection anchorSection;
98306995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9831a68b90caSToby Isaac 
9832a68b90caSToby Isaac   PetscFunctionBegin;
9833a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
98359566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
98369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
98376995de1eSToby Isaac   if (numFields) {
9838719ab38cSToby Isaac     PetscInt f;
98399566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
9840719ab38cSToby Isaac 
9841719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9842719ab38cSToby Isaac       PetscInt numComp;
9843719ab38cSToby Isaac 
98449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
98459566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
9846719ab38cSToby Isaac     }
98476995de1eSToby Isaac   }
98489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
98499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
98506995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
98516995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
98526995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
98539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
9854a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
98559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9856a68b90caSToby Isaac     if (dof) {
98579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
98589566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
9859a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
98609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
98619566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
9862a68b90caSToby Isaac       }
9863a68b90caSToby Isaac     }
9864a68b90caSToby Isaac   }
98659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
98669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
9867a68b90caSToby Isaac   PetscFunctionReturn(0);
9868a68b90caSToby Isaac }
9869a68b90caSToby Isaac 
9870d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9871d71ae5a4SJacob Faibussowitsch {
9872f7c74593SToby Isaac   PetscSection    aSec;
9873ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
98740ac89760SToby Isaac   const PetscInt *anchors;
98750ac89760SToby Isaac   PetscInt        numFields, f;
987666ad2231SToby Isaac   IS              aIS;
9877e19f7ee6SMark Adams   MatType         mtype;
9878e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
98790ac89760SToby Isaac 
98800ac89760SToby Isaac   PetscFunctionBegin;
98810ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
98839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
98849566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
98859566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
98869566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
98879566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
98889566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
98899566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
9890e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9891e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9892e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
98939566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
98949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
98959566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
98966995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
98979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
98989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
98999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
99000ac89760SToby Isaac   i[0] = 0;
99019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
99020ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9903f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9904f19733c5SToby Isaac 
99059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
9906f19733c5SToby Isaac     if (!rDof) continue;
99079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99080ac89760SToby Isaac     if (numFields) {
99090ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99100ac89760SToby Isaac         annz = 0;
9911f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9912f19733c5SToby Isaac           a = anchors[rOff + r];
9913ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
99149566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
99150ac89760SToby Isaac           annz += aDof;
99160ac89760SToby Isaac         }
99179566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99189566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
9919ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99200ac89760SToby Isaac       }
99212f7452b8SBarry Smith     } else {
99220ac89760SToby Isaac       annz = 0;
99239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99240ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9925ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9926ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
99279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
99280ac89760SToby Isaac         annz += aDof;
99290ac89760SToby Isaac       }
99309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
9932ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99330ac89760SToby Isaac     }
99340ac89760SToby Isaac   }
99350ac89760SToby Isaac   nnz = i[m];
99369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
99370ac89760SToby Isaac   offset = 0;
99380ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
99390ac89760SToby Isaac     if (numFields) {
99400ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99420ac89760SToby Isaac         for (q = 0; q < dof; q++) {
99430ac89760SToby Isaac           PetscInt rDof, rOff, r;
99449566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
99459566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99460ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
99470ac89760SToby Isaac             PetscInt s;
99480ac89760SToby Isaac 
99490ac89760SToby Isaac             a = anchors[rOff + r];
9950ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
99519566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
99529566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
9953ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
99540ac89760SToby Isaac           }
99550ac89760SToby Isaac         }
99560ac89760SToby Isaac       }
99572f7452b8SBarry Smith     } else {
99589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99590ac89760SToby Isaac       for (q = 0; q < dof; q++) {
99600ac89760SToby Isaac         PetscInt rDof, rOff, r;
99619566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
99629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99630ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
99640ac89760SToby Isaac           PetscInt s;
99650ac89760SToby Isaac 
99660ac89760SToby Isaac           a = anchors[rOff + r];
9967ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
99689566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
99699566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
9970ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
99710ac89760SToby Isaac         }
99720ac89760SToby Isaac       }
99730ac89760SToby Isaac     }
99740ac89760SToby Isaac   }
99759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
99769566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
99779566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
99789566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
99790ac89760SToby Isaac   PetscFunctionReturn(0);
99800ac89760SToby Isaac }
99810ac89760SToby Isaac 
9982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
9983d71ae5a4SJacob Faibussowitsch {
9984f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
9985f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
998666ad2231SToby Isaac   Mat          cMat;
998766ad2231SToby Isaac 
998866ad2231SToby Isaac   PetscFunctionBegin;
998966ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
999166ad2231SToby Isaac   if (anchorSection) {
999244a7f3ddSMatthew G. Knepley     PetscInt Nf;
9993e228b242SToby Isaac 
99949566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
99959566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
99969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
99979566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
99989566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
99999566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
100009566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
100019566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1000266ad2231SToby Isaac   }
1000366ad2231SToby Isaac   PetscFunctionReturn(0);
1000466ad2231SToby Isaac }
10005a93c429eSMatthew G. Knepley 
10006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10007d71ae5a4SJacob Faibussowitsch {
10008a93c429eSMatthew G. Knepley   IS           subis;
10009a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10010a93c429eSMatthew G. Knepley 
10011a93c429eSMatthew G. Knepley   PetscFunctionBegin;
100129566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1001328b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1001428b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10015a93c429eSMatthew G. Knepley   /* Create subdomain */
100169566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10017a93c429eSMatthew G. Knepley   /* Create submodel */
100189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
100199566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
100209566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
100219566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
100229566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10023a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10024a93c429eSMatthew G. Knepley   if (is) {
10025a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10026a93c429eSMatthew G. Knepley     IS              spIS;
10027a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10028a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10029a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10030a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10031a93c429eSMatthew G. Knepley 
100329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
100339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
100349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
100359566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
100369566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
100379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10038a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10039a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10040a93c429eSMatthew G. Knepley 
100419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10042a93c429eSMatthew G. Knepley       if (gdof > 0) {
10043a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10044a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10045a93c429eSMatthew G. Knepley 
100469566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
100479566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10048a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10049a93c429eSMatthew G. Knepley         }
10050a93c429eSMatthew G. Knepley         subSize += pSubSize;
10051a93c429eSMatthew G. Knepley         if (pSubSize) {
10052a93c429eSMatthew G. Knepley           if (bs < 0) {
10053a93c429eSMatthew G. Knepley             bs = pSubSize;
10054a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10055a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10056a93c429eSMatthew G. Knepley             bs = 1;
10057a93c429eSMatthew G. Knepley           }
10058a93c429eSMatthew G. Knepley         }
10059a93c429eSMatthew G. Knepley       }
10060a93c429eSMatthew G. Knepley     }
10061a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
100629371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
100639371c9d4SSatish Balay     bsLocal[1] = bs;
100649566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
100659371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
100669371c9d4SSatish Balay       bs = 1;
100679371c9d4SSatish Balay     } else {
100689371c9d4SSatish Balay       bs = bsMinMax[0];
100699371c9d4SSatish Balay     }
100709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10071a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10072a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10073a93c429eSMatthew G. Knepley 
100749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10075a93c429eSMatthew G. Knepley       if (gdof > 0) {
10076a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10077a93c429eSMatthew G. Knepley 
100789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10079a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10080a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10081a93c429eSMatthew G. Knepley 
10082a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10083a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
100849566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
100859566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10086a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10087a93c429eSMatthew G. Knepley           }
100889566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
100899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10090ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10091a93c429eSMatthew G. Knepley         }
10092a93c429eSMatthew G. Knepley       }
10093a93c429eSMatthew G. Knepley     }
100949566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
100959566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10096a93c429eSMatthew G. Knepley     if (bs > 1) {
10097a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10098a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10099a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10100a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
101019371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
101029371c9d4SSatish Balay             set = 0;
101039371c9d4SSatish Balay             break;
101049371c9d4SSatish Balay           }
10105a93c429eSMatthew G. Knepley         }
10106a93c429eSMatthew G. Knepley       }
101079566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10108a93c429eSMatthew G. Knepley     }
10109a93c429eSMatthew G. Knepley     /* Attach nullspace */
10110a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10111a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10112a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10113a93c429eSMatthew G. Knepley     }
10114a93c429eSMatthew G. Knepley     if (f < Nf) {
10115a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
101169566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
101176823f3c5SBlaise Bourdin 
101189566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
101199566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10120a93c429eSMatthew G. Knepley     }
10121a93c429eSMatthew G. Knepley   }
10122a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
10123a93c429eSMatthew G. Knepley }
10124c0f0dcc3SMatthew G. Knepley 
10125c0f0dcc3SMatthew G. Knepley /*@
10126c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10127c0f0dcc3SMatthew G. Knepley 
10128a1cb98faSBarry Smith   Input Parameters:
10129a1cb98faSBarry Smith + dm - The `DM`
10130a1cb98faSBarry Smith - dummy - unused argument
10131a1cb98faSBarry Smith 
10132a1cb98faSBarry Smith   Options Database Key:
10133a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10134c0f0dcc3SMatthew G. Knepley 
10135c0f0dcc3SMatthew G. Knepley   Level: developer
10136c0f0dcc3SMatthew G. Knepley 
10137a1cb98faSBarry Smith .seealso: [](chapter_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10138c0f0dcc3SMatthew G. Knepley @*/
10139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10140d71ae5a4SJacob Faibussowitsch {
10141e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
10142c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
10143c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
10144c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
10145c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
10146c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
10147c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
10148c0f0dcc3SMatthew G. Knepley   const char        *name;
10149e5ed2c37SJose E. Roman #endif
10150c0f0dcc3SMatthew G. Knepley 
10151c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
10152c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10153c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
101549566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
101559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
101569566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
101579566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
101589566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
101599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
101609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
10161c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart) * Nf * eventInfo.count;
10162c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops / eventInfo.time;
10163c0f0dcc3SMatthew G. Knepley   cellRate = N / eventInfo.time;
1016463a3b9bcSJacob 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)));
10165c0f0dcc3SMatthew G. Knepley #else
10166c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
10167c0f0dcc3SMatthew G. Knepley #endif
10168c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
10169c0f0dcc3SMatthew G. Knepley }
10170