xref: /petsc/src/dm/impls/plex/plex.c (revision 6302a7fbd3ef817afd9fd56e824b3764cbcb76cb)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>
3e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
48135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
50c312b8eSJed Brown #include <petscsf.h>
6e228b242SToby Isaac #include <petscds.h>
7e412dcbdSMatthew G. Knepley #include <petscdraw.h>
8f19dbd58SToby Isaac #include <petscdmfield.h>
9012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
10552f7358SJed Brown 
11552f7358SJed Brown /* Logging support */
1202f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints,DMPLEX_TopologyView,DMPLEX_LabelsView,DMPLEX_CoordinatesView,DMPLEX_SectionView,DMPLEX_GlobalVectorView,DMPLEX_LocalVectorView,DMPLEX_TopologyLoad,DMPLEX_LabelsLoad,DMPLEX_CoordinatesLoad,DMPLEX_SectionLoad,DMPLEX_GlobalVectorLoad,DMPLEX_LocalVectorLoad;
13552f7358SJed Brown 
145a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
15552f7358SJed Brown 
16e5337592SStefano Zampini /*@
179318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
189318fe57SMatthew G. Knepley 
199318fe57SMatthew G. Knepley   Input Parameter:
209318fe57SMatthew G. Knepley . dm      - The DMPlex object
219318fe57SMatthew G. Knepley 
229318fe57SMatthew G. Knepley   Output Parameter:
239318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
249318fe57SMatthew G. Knepley 
259318fe57SMatthew G. Knepley   Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
269318fe57SMatthew G. Knepley   If the mesh has no cells, this returns PETSC_FALSE.
279318fe57SMatthew G. Knepley 
289318fe57SMatthew G. Knepley   Level: intermediate
299318fe57SMatthew G. Knepley 
309318fe57SMatthew G. Knepley .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices()
319318fe57SMatthew G. Knepley @*/
329318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
339318fe57SMatthew G. Knepley {
349318fe57SMatthew G. Knepley   DMPolytopeType ct;
359318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
369318fe57SMatthew G. Knepley 
379318fe57SMatthew G. Knepley   PetscFunctionBegin;
389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
399318fe57SMatthew G. Knepley   if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);}
409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
419318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
429318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
439318fe57SMatthew G. Knepley }
449318fe57SMatthew G. Knepley 
459318fe57SMatthew G. Knepley /*@
46412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
47e5337592SStefano Zampini 
48d8d19677SJose E. Roman   Input Parameters:
49412e9a14SMatthew G. Knepley + dm     - The DMPlex object
50412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
51e5337592SStefano Zampini 
52e5337592SStefano Zampini   Output Parameters:
53412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
54412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
55e5337592SStefano Zampini 
56412e9a14SMatthew G. Knepley   Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
57e5337592SStefano Zampini 
58412e9a14SMatthew G. Knepley   Level: developer
59e5337592SStefano Zampini 
608065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
61e5337592SStefano Zampini @*/
62412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
63e5337592SStefano Zampini {
64412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
65412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
66e5337592SStefano Zampini 
67e5337592SStefano Zampini   PetscFunctionBegin;
689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
69412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
70412e9a14SMatthew G. Knepley     DMPolytopeType cct;
71412e9a14SMatthew G. Knepley 
729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &cct));
73412e9a14SMatthew G. Knepley     if ((PetscInt) cct < 0) break;
74412e9a14SMatthew G. Knepley     switch (cct) {
75ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_POINT:
76ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
77ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
78ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
79ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:
80ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
81412e9a14SMatthew G. Knepley         ct = cct;
82e5337592SStefano Zampini         break;
83412e9a14SMatthew G. Knepley       default: break;
84e5337592SStefano Zampini     }
85412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
86e5337592SStefano Zampini   }
87412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
88412e9a14SMatthew G. Knepley     DMLabel ctLabel;
89412e9a14SMatthew G. Knepley 
909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
919566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE));
92e5337592SStefano Zampini   }
93412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
94412e9a14SMatthew G. Knepley   if (cEnd)   *cEnd   = cE;
95e5337592SStefano Zampini   PetscFunctionReturn(0);
96e5337592SStefano Zampini }
97e5337592SStefano Zampini 
987afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
997e42fee7SMatthew G. Knepley {
100412e9a14SMatthew G. Knepley   PetscInt       cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
101a99a26bcSAdrian Croucher   PetscInt       vcdof[2] = {0,0}, globalvcdof[2];
1027e42fee7SMatthew G. Knepley 
1037e42fee7SMatthew G. Knepley   PetscFunctionBegin;
104e630c359SToby Isaac   *ft  = PETSC_VTK_INVALID;
1059566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1097e42fee7SMatthew G. Knepley   if (field >= 0) {
1109566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1119566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1127e42fee7SMatthew G. Knepley   } else {
1139566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
1149566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
1157e42fee7SMatthew G. Knepley   }
1169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
117a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1187e42fee7SMatthew G. Knepley     *sStart = vStart;
1197e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
120f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1217e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_POINT_FIELD;
122a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1237e42fee7SMatthew G. Knepley     *sStart = cStart;
1247e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
125f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1267e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_CELL_FIELD;
127e630c359SToby Isaac   } else {
128e630c359SToby Isaac     if (field >= 0) {
129e630c359SToby Isaac       const char *fieldname;
130e630c359SToby Isaac 
1319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
1329566063dSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname));
133e630c359SToby Isaac     } else {
1349566063dSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n"));
135e630c359SToby Isaac     }
136e630c359SToby Isaac   }
1377e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
1387e42fee7SMatthew G. Knepley }
1397e42fee7SMatthew G. Knepley 
1406913077dSMatthew G. Knepley /*@
1416913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
1426913077dSMatthew G. Knepley 
1436913077dSMatthew G. Knepley   Collective on dm
1446913077dSMatthew G. Knepley 
1456913077dSMatthew G. Knepley   Input Parameters:
1466913077dSMatthew G. Knepley + dm - The DMPlex
1476913077dSMatthew G. Knepley . n  - The number of vectors
1486913077dSMatthew G. Knepley . u  - The array of local vectors
1496913077dSMatthew G. Knepley - viewer - The Draw viewer
1506913077dSMatthew G. Knepley 
1516913077dSMatthew G. Knepley   Level: advanced
1526913077dSMatthew G. Knepley 
1536913077dSMatthew G. Knepley .seealso: VecViewFromOptions(), VecView()
1546913077dSMatthew G. Knepley @*/
1556913077dSMatthew G. Knepley PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
1566913077dSMatthew G. Knepley {
1576913077dSMatthew G. Knepley   PetscDS            ds;
1586913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
1596913077dSMatthew G. Knepley   PetscDrawLG        lg;
1606913077dSMatthew G. Knepley   Vec                coordinates;
1616913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
1626913077dSMatthew G. Knepley   PetscReal         *vals;
1636913077dSMatthew G. Knepley   PetscInt          *Nc;
1646913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
1656913077dSMatthew G. Knepley   char             **names;
1666913077dSMatthew G. Knepley 
1676913077dSMatthew G. Knepley   PetscFunctionBegin;
1689566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
1699566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
1709566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
1719566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
1726913077dSMatthew G. Knepley 
1739566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1746913077dSMatthew G. Knepley   if (!draw) PetscFunctionReturn(0);
1759566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n*Nl, &lg));
1766913077dSMatthew G. Knepley 
1779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n*Nl, &names, n*Nl, &vals));
1786913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
1796913077dSMatthew G. Knepley     const char *vname;
1806913077dSMatthew G. Knepley 
1819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) u[i], &vname));
1826913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
1836913077dSMatthew G. Knepley       PetscObject disc;
1846913077dSMatthew G. Knepley       const char *fname;
1856913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
1866913077dSMatthew G. Knepley 
1879566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
1886913077dSMatthew G. Knepley       /* TODO Create names for components */
1896913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
1909566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
1919566063dSJacob Faibussowitsch         PetscCall(PetscStrcpy(tmpname, vname));
1929566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN));
1939566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN));
1949566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
1956913077dSMatthew G. Knepley       }
1966913077dSMatthew G. Knepley     }
1976913077dSMatthew G. Knepley   }
1989566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *) names));
1996913077dSMatthew G. Knepley   /* Just add P_1 support for now */
2009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2029566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
2039566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
2046913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2056913077dSMatthew G. Knepley     PetscScalar *x, *svals;
2066913077dSMatthew G. Knepley 
2079566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
2086913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
2099566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
2106913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i*Nl + l] = PetscRealPart(svals[l]);
2116913077dSMatthew G. Knepley     }
2129566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
2136913077dSMatthew G. Knepley   }
2149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2159566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
2169566063dSJacob Faibussowitsch   for (l = 0; l < n*Nl; ++l) PetscCall(PetscFree(names[l]));
2179566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
2186913077dSMatthew G. Knepley 
2199566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
2209566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
2216913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2226913077dSMatthew G. Knepley }
2236913077dSMatthew G. Knepley 
2246913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
2256913077dSMatthew G. Knepley {
2266913077dSMatthew G. Knepley   DM             dm;
2276913077dSMatthew G. Knepley 
2286913077dSMatthew G. Knepley   PetscFunctionBegin;
2299566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
2309566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
2316913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2326913077dSMatthew G. Knepley }
2336913077dSMatthew G. Knepley 
2346913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
235e412dcbdSMatthew G. Knepley {
236e412dcbdSMatthew G. Knepley   DM                 dm;
237d1df6f1dSMatthew G. Knepley   PetscSection       s;
238e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
239e412dcbdSMatthew G. Knepley   DM                 cdm;
240e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
241e412dcbdSMatthew G. Knepley   Vec                coordinates;
242e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
243e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
244339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
2456913077dSMatthew G. Knepley   PetscBool          flg;
246d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
247e412dcbdSMatthew G. Knepley   const char        *name;
248339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
249e412dcbdSMatthew G. Knepley 
250e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
2519566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2529566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
2539566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
2549566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
2559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
2569566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
2579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
2589566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
2599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
262e412dcbdSMatthew G. Knepley 
2639566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &name));
2649566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
265e412dcbdSMatthew G. Knepley 
2669566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
2679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
268e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
2690c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
2700c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
271e412dcbdSMatthew G. Knepley   }
2729566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2739566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
274e412dcbdSMatthew G. Knepley 
275d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
276d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
277d1df6f1dSMatthew G. Knepley     DM   fdm = dm;
278d1df6f1dSMatthew G. Knepley     Vec  fv  = v;
279d1df6f1dSMatthew G. Knepley     IS   fis;
280d1df6f1dSMatthew G. Knepley     char prefix[PETSC_MAX_PATH_LEN];
281d1df6f1dSMatthew G. Knepley     const char *fname;
282d1df6f1dSMatthew G. Knepley 
2839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
285d1df6f1dSMatthew G. Knepley 
2869566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix)));
287d1df6f1dSMatthew G. Knepley     else               {prefix[0] = '\0';}
288d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
2899566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
2909566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
2919566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname,sizeof(prefix)));
2929566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_",sizeof(prefix)));
293d1df6f1dSMatthew G. Knepley     }
294d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
295d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
296d1df6f1dSMatthew G. Knepley 
2979566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
2989566063dSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time));
2999566063dSJacob Faibussowitsch       else        PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time));
3009566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
301d1df6f1dSMatthew G. Knepley 
302d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3039566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
304339e3443SMatthew G. Knepley       if (!flg) {
3059566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
3069566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
307d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
308339e3443SMatthew G. Knepley       }
3099566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
3109566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
3119566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]));
312e412dcbdSMatthew G. Knepley 
3139566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
314e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
31599a2f7bcSMatthew G. Knepley         PetscScalar *coords = NULL, *a = NULL;
316e56f9228SJed Brown         PetscInt     numCoords, color[4] = {-1,-1,-1,-1};
317e412dcbdSMatthew G. Knepley 
3189566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
319339e3443SMatthew G. Knepley         if (a) {
320d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
321339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
322339e3443SMatthew G. Knepley         } else {
323339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
324339e3443SMatthew G. Knepley           PetscInt     numVals, va;
325339e3443SMatthew G. Knepley 
3269566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
3272c71b3e2SJacob Faibussowitsch           PetscCheckFalse(numVals % Nc,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals);
328d1df6f1dSMatthew G. Knepley           switch (numVals/Nc) {
329d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
330d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
331d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]);
332339e3443SMatthew G. Knepley             break;
333d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
334d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
335d1df6f1dSMatthew 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]);
336d1df6f1dSMatthew G. Knepley             break;
33798921bdaSJacob Faibussowitsch           default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc);
338339e3443SMatthew G. Knepley           }
3399566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
340339e3443SMatthew G. Knepley         }
3419566063dSJacob Faibussowitsch         PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
342e412dcbdSMatthew G. Knepley         switch (numCoords) {
343e412dcbdSMatthew G. Knepley         case 6:
3449edc3542SMatthew Knepley         case 12: /* Localized triangle */
3459566063dSJacob 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]));
346e412dcbdSMatthew G. Knepley           break;
347e412dcbdSMatthew G. Knepley         case 8:
3489edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
3499566063dSJacob 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]));
3509566063dSJacob 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]));
351e412dcbdSMatthew G. Knepley           break;
35298921bdaSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords);
353e412dcbdSMatthew G. Knepley         }
3549566063dSJacob Faibussowitsch         PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
355e412dcbdSMatthew G. Knepley       }
3569566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
3579566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
3589566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
3599566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
360d1df6f1dSMatthew G. Knepley     }
361d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3629566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
3639566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
3649566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
365d1df6f1dSMatthew G. Knepley     }
366d1df6f1dSMatthew G. Knepley   }
367e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
368e412dcbdSMatthew G. Knepley }
369e412dcbdSMatthew G. Knepley 
3706913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
3716913077dSMatthew G. Knepley {
3726913077dSMatthew G. Knepley   DM        dm;
3736913077dSMatthew G. Knepley   PetscDraw draw;
3746913077dSMatthew G. Knepley   PetscInt  dim;
3756913077dSMatthew G. Knepley   PetscBool isnull;
3766913077dSMatthew G. Knepley 
3776913077dSMatthew G. Knepley   PetscFunctionBegin;
3789566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3799566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
3806913077dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
3816913077dSMatthew G. Knepley 
3829566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3839566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3846913077dSMatthew G. Knepley   switch (dim) {
3859566063dSJacob Faibussowitsch   case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));break;
3869566063dSJacob Faibussowitsch   case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));break;
3875f80ce2aSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject) v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
3886913077dSMatthew G. Knepley   }
3896913077dSMatthew G. Knepley   PetscFunctionReturn(0);
3906913077dSMatthew G. Knepley }
3916913077dSMatthew G. Knepley 
392684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
393684b87d9SLisandro Dalcin {
394684b87d9SLisandro Dalcin   DM                      dm;
395684b87d9SLisandro Dalcin   Vec                     locv;
396684b87d9SLisandro Dalcin   const char              *name;
397684b87d9SLisandro Dalcin   PetscSection            section;
398684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
399e630c359SToby Isaac   PetscInt                numFields;
400684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
401684b87d9SLisandro Dalcin 
402684b87d9SLisandro Dalcin   PetscFunctionBegin;
4039566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4049566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4059566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &name));
4069566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) locv, name));
4079566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4089566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
410e630c359SToby Isaac   if (!numFields) {
4119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4129566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv));
413e630c359SToby Isaac   } else {
414e630c359SToby Isaac     PetscInt f;
415e630c359SToby Isaac 
416e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
418e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4199566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4209566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv));
421e630c359SToby Isaac     }
4229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
423e630c359SToby Isaac   }
424684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
425684b87d9SLisandro Dalcin }
426684b87d9SLisandro Dalcin 
427552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
428552f7358SJed Brown {
429552f7358SJed Brown   DM             dm;
430684b87d9SLisandro Dalcin   PetscBool      isvtk, ishdf5, isdraw, isglvis;
431552f7358SJed Brown 
432552f7358SJed Brown   PetscFunctionBegin;
4339566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
43428b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk));
4369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5));
4379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,  &isdraw));
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis));
439684b87d9SLisandro Dalcin   if (isvtk || ishdf5 || isdraw || isglvis) {
440684b87d9SLisandro Dalcin     PetscInt    i,numFields;
441684b87d9SLisandro Dalcin     PetscObject fe;
442ef31f671SMatthew G. Knepley     PetscBool   fem = PETSC_FALSE;
443684b87d9SLisandro Dalcin     Vec         locv = v;
444684b87d9SLisandro Dalcin     const char  *name;
445684b87d9SLisandro Dalcin     PetscInt    step;
446684b87d9SLisandro Dalcin     PetscReal   time;
447ef31f671SMatthew G. Knepley 
4489566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
449684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
4509566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
451684b87d9SLisandro Dalcin       if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; }
452ef31f671SMatthew G. Knepley     }
453684b87d9SLisandro Dalcin     if (fem) {
454798534f6SMatthew G. Knepley       PetscObject isZero;
455798534f6SMatthew G. Knepley 
4569566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4579566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) v, &name));
4589566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject) locv, name));
4599566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
4609566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
4619566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4629566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4639566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
464ef31f671SMatthew G. Knepley     }
465552f7358SJed Brown     if (isvtk) {
4669566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
467b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
468b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4699566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
470b136c2c9SMatthew G. Knepley #else
471b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
472b136c2c9SMatthew G. Knepley #endif
473f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4749566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
475684b87d9SLisandro Dalcin     } else if (isglvis) {
4769566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
4779566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
4789566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
479684b87d9SLisandro Dalcin     }
480798534f6SMatthew G. Knepley     if (fem) {
4819566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
4829566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
483798534f6SMatthew G. Knepley     }
484552f7358SJed Brown   } else {
485684b87d9SLisandro Dalcin     PetscBool isseq;
486684b87d9SLisandro Dalcin 
4879566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
4889566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
4899566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
490552f7358SJed Brown   }
491552f7358SJed Brown   PetscFunctionReturn(0);
492552f7358SJed Brown }
493552f7358SJed Brown 
494552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
495552f7358SJed Brown {
496552f7358SJed Brown   DM        dm;
4976823f3c5SBlaise Bourdin   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii;
498552f7358SJed Brown 
499552f7358SJed Brown   PetscFunctionBegin;
5009566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
50128b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
5039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
507684b87d9SLisandro Dalcin   if (isvtk || isdraw || isglvis) {
508552f7358SJed Brown     Vec         locv;
509798534f6SMatthew G. Knepley     PetscObject isZero;
510552f7358SJed Brown     const char *name;
511552f7358SJed Brown 
5129566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5139566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
5149566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) locv, name));
5159566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5169566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5179566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
5189566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
5199566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5209566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
5219566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
522b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
523b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5249566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
525b136c2c9SMatthew G. Knepley #else
526b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
527b136c2c9SMatthew G. Knepley #endif
5286823f3c5SBlaise Bourdin   } else if (isexodusii) {
5296823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5309566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5316823f3c5SBlaise Bourdin #else
5326823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5336823f3c5SBlaise Bourdin #endif
534552f7358SJed Brown   } else {
535684b87d9SLisandro Dalcin     PetscBool isseq;
536684b87d9SLisandro Dalcin 
5379566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5389566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5399566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
540552f7358SJed Brown   }
541552f7358SJed Brown   PetscFunctionReturn(0);
542552f7358SJed Brown }
543552f7358SJed Brown 
544d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
545d930f514SMatthew G. Knepley {
546d930f514SMatthew G. Knepley   DM                dm;
547d930f514SMatthew G. Knepley   MPI_Comm          comm;
548d930f514SMatthew G. Knepley   PetscViewerFormat format;
549d930f514SMatthew G. Knepley   Vec               v;
550d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
551d930f514SMatthew G. Knepley 
552d930f514SMatthew G. Knepley   PetscFunctionBegin;
5539566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5549566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) originalv, &comm));
55528b400f6SJacob Faibussowitsch   PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5569566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,  &isvtk));
559d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
560a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
561a8ad634aSStefano Zampini     /* this need a better fix */
562a8ad634aSStefano Zampini     if (dm->useNatural) {
563a8ad634aSStefano Zampini       if (dm->sfNatural) {
564d930f514SMatthew G. Knepley         const char *vecname;
565d930f514SMatthew G. Knepley         PetscInt    n, nroots;
566d930f514SMatthew G. Knepley 
5679566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5689566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
569d930f514SMatthew G. Knepley         if (n == nroots) {
5709566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
5719566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5729566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5739566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
5749566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
575d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
576d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
577a8ad634aSStefano Zampini     } else v = originalv;
578a8ad634aSStefano Zampini   } else v = originalv;
579a8ad634aSStefano Zampini 
580d930f514SMatthew G. Knepley   if (ishdf5) {
581d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5829566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
583d930f514SMatthew G. Knepley #else
584d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
585d930f514SMatthew G. Knepley #endif
586d930f514SMatthew G. Knepley   } else if (isvtk) {
587d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
588d930f514SMatthew G. Knepley   } else {
589d930f514SMatthew G. Knepley     PetscBool isseq;
590d930f514SMatthew G. Knepley 
5919566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5929566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5939566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
594d930f514SMatthew G. Knepley   }
5959566063dSJacob Faibussowitsch   if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v));
596d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
597d930f514SMatthew G. Knepley }
598d930f514SMatthew G. Knepley 
5992c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
6002c40f234SMatthew G. Knepley {
6012c40f234SMatthew G. Knepley   DM             dm;
6022c40f234SMatthew G. Knepley   PetscBool      ishdf5;
6032c40f234SMatthew G. Knepley 
6042c40f234SMatthew G. Knepley   PetscFunctionBegin;
6059566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
60628b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
6082c40f234SMatthew G. Knepley   if (ishdf5) {
6092c40f234SMatthew G. Knepley     DM          dmBC;
6102c40f234SMatthew G. Knepley     Vec         gv;
6112c40f234SMatthew G. Knepley     const char *name;
6122c40f234SMatthew G. Knepley 
6139566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6149566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6159566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
6169566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) gv, name));
6179566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6189566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6199566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6209566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6212c40f234SMatthew G. Knepley   } else {
6229566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(v, viewer));
6232c40f234SMatthew G. Knepley   }
6242c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
6252c40f234SMatthew G. Knepley }
6262c40f234SMatthew G. Knepley 
6272c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
6282c40f234SMatthew G. Knepley {
6292c40f234SMatthew G. Knepley   DM             dm;
6306823f3c5SBlaise Bourdin   PetscBool      ishdf5,isexodusii;
6312c40f234SMatthew G. Knepley 
6322c40f234SMatthew G. Knepley   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63428b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
6369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
6372c40f234SMatthew G. Knepley   if (ishdf5) {
638878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6399566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
640b136c2c9SMatthew G. Knepley #else
641b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
642878b459fSMatthew G. Knepley #endif
6436823f3c5SBlaise Bourdin   } else if (isexodusii) {
6446823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6459566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6466823f3c5SBlaise Bourdin #else
6476823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6486823f3c5SBlaise Bourdin #endif
6492c40f234SMatthew G. Knepley   } else {
6509566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(v, viewer));
651552f7358SJed Brown   }
652552f7358SJed Brown   PetscFunctionReturn(0);
653552f7358SJed Brown }
654552f7358SJed Brown 
655d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
656d930f514SMatthew G. Knepley {
657d930f514SMatthew G. Knepley   DM                dm;
658d930f514SMatthew G. Knepley   PetscViewerFormat format;
659d930f514SMatthew G. Knepley   PetscBool         ishdf5;
660d930f514SMatthew G. Knepley 
661d930f514SMatthew G. Knepley   PetscFunctionBegin;
6629566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
66328b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6649566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
666d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
667a8ad634aSStefano Zampini     if (dm->useNatural) {
668d930f514SMatthew G. Knepley       if (dm->sfNatural) {
669d930f514SMatthew G. Knepley         if (ishdf5) {
670d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
671d930f514SMatthew G. Knepley           Vec         v;
672d930f514SMatthew G. Knepley           const char *vecname;
673d930f514SMatthew G. Knepley 
6749566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
6759566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
6769566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
6779566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6789566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
6799566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
6809566063dSJacob Faibussowitsch           PetscCall(DMRestoreGlobalVector(dm, &v));
681d930f514SMatthew G. Knepley #else
682d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
683d930f514SMatthew G. Knepley #endif
684d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
685d930f514SMatthew G. Knepley       }
686a8ad634aSStefano Zampini     } else {
6879566063dSJacob Faibussowitsch       PetscCall(VecLoad_Default(originalv, viewer));
688a8ad634aSStefano Zampini     }
689d930f514SMatthew G. Knepley   }
690d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
691d930f514SMatthew G. Knepley }
692d930f514SMatthew G. Knepley 
6937cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
694731e8ddeSMatthew G. Knepley {
695731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
696731e8ddeSMatthew G. Knepley   Vec                coordinates;
697ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
698731e8ddeSMatthew G. Knepley   const char        *name[4];
699731e8ddeSMatthew G. Knepley   const PetscScalar *a;
700731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
701731e8ddeSMatthew G. Knepley 
702731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7049566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7059566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7109566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
711731e8ddeSMatthew G. Knepley   name[0]     = "vertex";
712731e8ddeSMatthew G. Knepley   name[1]     = "edge";
713731e8ddeSMatthew G. Knepley   name[dim-1] = "face";
714731e8ddeSMatthew G. Knepley   name[dim]   = "cell";
715731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
716731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
717ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
718731e8ddeSMatthew G. Knepley 
7199566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
7209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]));
7219566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
723731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
724731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
725731e8ddeSMatthew G. Knepley 
726731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
728731e8ddeSMatthew G. Knepley       if (!dof) continue;
7299566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
7319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point));
732731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
7339566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
734731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7359566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7369566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d])));
737731e8ddeSMatthew G. Knepley         }
7389566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
739731e8ddeSMatthew G. Knepley       }
7409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
741731e8ddeSMatthew G. Knepley     }
7429566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
744731e8ddeSMatthew G. Knepley   }
7459566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
746731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
747731e8ddeSMatthew G. Knepley }
748731e8ddeSMatthew G. Knepley 
74919ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem;
75019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
75119ad8254SMatthew G. Knepley 
75219ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
75319ad8254SMatthew G. Knepley {
75419ad8254SMatthew G. Knepley   PetscInt       i;
75519ad8254SMatthew G. Knepley 
75619ad8254SMatthew G. Knepley   PetscFunctionBegin;
75719ad8254SMatthew G. Knepley   if (dim > 3) {
7589566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i])));
75919ad8254SMatthew G. Knepley   } else {
76019ad8254SMatthew G. Knepley     PetscReal coords[3], trcoords[3];
76119ad8254SMatthew G. Knepley 
76219ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
76319ad8254SMatthew G. Knepley     switch (cs) {
76419ad8254SMatthew G. Knepley       case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break;
76519ad8254SMatthew G. Knepley       case CS_POLAR:
7662c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dim != 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim);
76719ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
76819ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
76919ad8254SMatthew G. Knepley         break;
77019ad8254SMatthew G. Knepley       case CS_CYLINDRICAL:
7712c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim);
77219ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
77319ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
77419ad8254SMatthew G. Knepley         trcoords[2] = coords[2];
77519ad8254SMatthew G. Knepley         break;
77619ad8254SMatthew G. Knepley       case CS_SPHERICAL:
7772c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim);
77819ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
77919ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
78019ad8254SMatthew G. Knepley         trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
78119ad8254SMatthew G. Knepley         break;
78219ad8254SMatthew G. Knepley     }
7839566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]));
78419ad8254SMatthew G. Knepley   }
78519ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
78619ad8254SMatthew G. Knepley }
78719ad8254SMatthew G. Knepley 
7887cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
789552f7358SJed Brown {
790552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
791552f7358SJed Brown   DM                cdm;
792552f7358SJed Brown   PetscSection      coordSection;
793552f7358SJed Brown   Vec               coordinates;
794552f7358SJed Brown   PetscViewerFormat format;
795552f7358SJed Brown 
796552f7358SJed Brown   PetscFunctionBegin;
7979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
7989566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
7999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8009566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
801552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
802552f7358SJed Brown     const char *name;
803f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8049318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
805552f7358SJed Brown     PetscMPIInt rank, size;
806552f7358SJed Brown 
8079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8099566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
8109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8129566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
8149566063dSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
8159566063dSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s"));
8169566063dSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight));
8179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n", name));
8189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize));
820552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
821552f7358SJed Brown       PetscInt dof, off, s;
822552f7358SJed Brown 
8239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
825552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
8269566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]));
827552f7358SJed Brown       }
828552f7358SJed Brown     }
8299566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n", name));
8319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize));
832552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
833552f7358SJed Brown       PetscInt dof, off, c;
834552f7358SJed Brown 
8359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
837552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
8389566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
839552f7358SJed Brown       }
840552f7358SJed Brown     }
8419566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8433d2e540fSStefano Zampini     if (coordSection && coordinates) {
84419ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
84519ad8254SMatthew G. Knepley       const PetscScalar *array;
84619ad8254SMatthew G. Knepley       PetscInt           Nf, Nc, pStart, pEnd, p;
84719ad8254SMatthew G. Knepley       PetscMPIInt        rank;
84819ad8254SMatthew G. Knepley       const char        *name;
84919ad8254SMatthew G. Knepley 
8509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL));
8519566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
8532c71b3e2SJacob Faibussowitsch       PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf);
8549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8569566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) coordinates, &name));
8579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf));
8589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %D components\n", Nc));
8599566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
86019ad8254SMatthew G. Knepley 
8619566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
86419ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
86519ad8254SMatthew G. Knepley         PetscInt dof, off;
86619ad8254SMatthew G. Knepley 
8679566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, p, &dof));
8689566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, p, &off));
8699566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4D) dim %2D offset %3D", p, dof, off));
8709566063dSJacob Faibussowitsch         PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
8719566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
87219ad8254SMatthew G. Knepley       }
8739566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
8749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8759566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
8763d2e540fSStefano Zampini     }
8779566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
8789566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
8799318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
8809318fe57SMatthew G. Knepley       DMLabel     label;
8819318fe57SMatthew G. Knepley       PetscBool   isdepth;
8829318fe57SMatthew G. Knepley       const char *name;
8839318fe57SMatthew G. Knepley 
8849566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
8859566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
8869318fe57SMatthew G. Knepley       if (isdepth) continue;
8879566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
8889566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
8899318fe57SMatthew G. Knepley     }
890552f7358SJed Brown     if (size > 1) {
891552f7358SJed Brown       PetscSF sf;
892552f7358SJed Brown 
8939566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
8949566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
895552f7358SJed Brown     }
8969566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
897552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
8980588280cSMatthew G. Knepley     const char  *name, *color;
8990588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9000588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
901fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
902552f7358SJed Brown     PetscReal    scale         = 2.0;
90378081901SStefano Zampini     PetscReal    tikzscale     = 1.0;
904b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers    = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9050588280cSMatthew G. Knepley     double       tcoords[3];
906552f7358SJed Brown     PetscScalar *coords;
907b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
908552f7358SJed Brown     PetscMPIInt  rank, size;
9090588280cSMatthew G. Knepley     char         **names, **colors, **lcolors;
910b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
911fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
912fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
913552f7358SJed Brown 
9149566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9169566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9170588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9180588280cSMatthew G. Knepley     numColors  = 10;
9190588280cSMatthew G. Knepley     numLColors = 10;
9209566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9229566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9239566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
924b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
925b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d]  = PETSC_TRUE;
926b7f6ffafSMatthew G. Knepley     n = 4;
9279566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9282c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1);
9299566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9302c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1);
9319566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9320588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9339566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9340588280cSMatthew G. Knepley     if (!useColors) {
9350588280cSMatthew G. Knepley       numColors = 3;
9369566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9370588280cSMatthew G. Knepley     }
9389566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9390588280cSMatthew G. Knepley     if (!useColors) {
9400588280cSMatthew G. Knepley       numLColors = 4;
9419566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9420588280cSMatthew G. Knepley     }
9439566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
944b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
9459566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
9462c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg && plotEdges && depth < dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated");
947202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
9489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
949fe1cc32dSStefano Zampini 
950fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
9519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
955fe1cc32dSStefano Zampini     if (lflg) {
956fe1cc32dSStefano Zampini       DMLabel lbl;
957fe1cc32dSStefano Zampini 
9589566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
959fe1cc32dSStefano Zampini       if (lbl) {
960fe1cc32dSStefano Zampini         PetscInt val, defval;
961fe1cc32dSStefano Zampini 
9629566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
9639566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd-pStart, &wp));
964fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
965fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
966fe1cc32dSStefano Zampini           PetscInt  closureSize;
967fe1cc32dSStefano Zampini 
9689566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
969fe1cc32dSStefano Zampini           if (val == defval) continue;
970fe1cc32dSStefano Zampini 
9719566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
972fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
9739566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(wp, closure[p] - pStart));
974fe1cc32dSStefano Zampini           }
9759566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
976fe1cc32dSStefano Zampini         }
977fe1cc32dSStefano Zampini       }
978fe1cc32dSStefano Zampini     }
979fe1cc32dSStefano Zampini 
9809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9829566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
9839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
9840588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
985552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
986552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
987552f7358SJed Brown \\usetikzlibrary{arrows}\n\
9885f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
9890588280cSMatthew G. Knepley     if (size > 1) {
9909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
991770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
992770b213bSMatthew G Knepley         if (p > 0 && p == size-1) {
9939566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p));
994770b213bSMatthew G Knepley         } else if (p > 0) {
9959566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p));
996770b213bSMatthew G Knepley         }
9979566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p));
998770b213bSMatthew G Knepley       }
9999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10000588280cSMatthew G. Knepley     }
1001b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1002b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart));
1003b7f6ffafSMatthew G. Knepley 
10049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart));
10059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1));
10069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart));
10079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.));
10089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart));
10099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1));
10109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.));
10119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart));
10129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart));
10139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1));
10149566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart));
10159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.));
1016b7f6ffafSMatthew G. Knepley     }
10179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale));
1018fe1cc32dSStefano Zampini 
1019552f7358SJed Brown     /* Plot vertices */
10209566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1022552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1023552f7358SJed Brown       PetscInt  off, dof, d;
10240588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1025552f7358SJed Brown 
1026fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,v - pStart)) continue;
10279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
10305f80ce2aSJacob Faibussowitsch       PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof);
10310588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10320588280cSMatthew G. Knepley         tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1033c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10340588280cSMatthew G. Knepley       }
10350588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10360588280cSMatthew G. Knepley       if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1037552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10389566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10399566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]));
1040552f7358SJed Brown       }
1041b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0%numColors];
1042b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
10430588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10440588280cSMatthew G. Knepley         PetscInt val;
10459566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10460588280cSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
10470588280cSMatthew G. Knepley       }
1048b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
10499566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v));
1050b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
10519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
1052b7f6ffafSMatthew G. Knepley       } else {
10539566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank));
10540588280cSMatthew G. Knepley       }
1055552f7358SJed Brown     }
10569566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
10579566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1058b7f6ffafSMatthew G. Knepley     /* Plot edges */
1059b7f6ffafSMatthew G. Knepley     if (plotEdges) {
10609566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
10619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1062b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1063b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1064b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1065b7f6ffafSMatthew G. Knepley 
1066b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
10679566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
10682c71b3e2SJacob Faibussowitsch         PetscCheckFalse(coneSize != 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize);
10699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
10709566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
10719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
10729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
10739566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1074b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1075b7f6ffafSMatthew G. Knepley           tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d]));
1076b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1077b7f6ffafSMatthew G. Knepley         }
1078b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1079b7f6ffafSMatthew G. Knepley         if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1080b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
10819566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10829566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1083b7f6ffafSMatthew G. Knepley         }
1084b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1%numColors];
1085b7f6ffafSMatthew G. Knepley         else           color = colors[rank%numColors];
1086b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1087b7f6ffafSMatthew G. Knepley           PetscInt val;
10889566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
1089b7f6ffafSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1090b7f6ffafSMatthew G. Knepley         }
10919566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e));
1092b7f6ffafSMatthew G. Knepley       }
10939566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
10949566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
10959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1096b7f6ffafSMatthew G. Knepley     }
1097846a3e8bSMatthew G. Knepley     /* Plot cells */
1098b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1099846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1100846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1101846a3e8bSMatthew G. Knepley 
1102fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
1103846a3e8bSMatthew G. Knepley         color = colors[rank%numColors];
1104846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1105846a3e8bSMatthew G. Knepley           PetscInt val;
11069566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
1107846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1108846a3e8bSMatthew G. Knepley         }
11099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
11109566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank));
1111846a3e8bSMatthew G. Knepley       }
1112846a3e8bSMatthew G. Knepley     } else {
1113b7f6ffafSMatthew G. Knepley        DMPolytopeType ct;
1114846a3e8bSMatthew G. Knepley 
1115b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1116b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1117fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11189566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1119b7f6ffafSMatthew G. Knepley         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR ||
1120b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_TRI_PRISM_TENSOR ||
1121b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1122b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1123b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1124b7f6ffafSMatthew G. Knepley 
11259566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11269566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1127b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1128b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1129b7f6ffafSMatthew G. Knepley 
11309566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
11319566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d) -- (%D_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank));
1132b7f6ffafSMatthew G. Knepley           }
1133b7f6ffafSMatthew G. Knepley         } else {
1134b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1135b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1136b7f6ffafSMatthew G. Knepley 
11379566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1138846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize*2; p += 2) {
1139846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1140846a3e8bSMatthew G. Knepley 
1141b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1142846a3e8bSMatthew G. Knepley           }
11439566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]));
1144b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1145b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v%Nv];
1146b7f6ffafSMatthew G. Knepley 
1147b7f6ffafSMatthew G. Knepley             if (v > 0) {
1148b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1149b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1150b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1151b7f6ffafSMatthew G. Knepley 
1152b7f6ffafSMatthew G. Knepley                 endpoints[0] = closure[v-1]; endpoints[1] = vertex;
11539566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
11542c71b3e2SJacob Faibussowitsch                 PetscCheckFalse(ne != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]);
11559566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank));
11569566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
1157b7f6ffafSMatthew G. Knepley               } else {
11589566063dSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1159b7f6ffafSMatthew G. Knepley               }
1160b7f6ffafSMatthew G. Knepley             }
11619566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank));
1162b7f6ffafSMatthew G. Knepley           }
11639566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
11649566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1165846a3e8bSMatthew G. Knepley         }
1166846a3e8bSMatthew G. Knepley       }
1167b7f6ffafSMatthew G. Knepley     }
11689566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1169846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1170846a3e8bSMatthew G. Knepley       double    ccoords[3] = {0.0, 0.0, 0.0};
1171846a3e8bSMatthew G. Knepley       PetscBool isLabeled  = PETSC_FALSE;
1172846a3e8bSMatthew G. Knepley       PetscInt *closure    = NULL;
1173846a3e8bSMatthew G. Knepley       PetscInt  closureSize, dof, d, n = 0;
1174846a3e8bSMatthew G. Knepley 
1175fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,c - pStart)) continue;
11769566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
11779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1178846a3e8bSMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1179846a3e8bSMatthew G. Knepley         const PetscInt point = closure[p];
1180846a3e8bSMatthew G. Knepley         PetscInt       off;
1181846a3e8bSMatthew G. Knepley 
1182846a3e8bSMatthew G. Knepley         if ((point < vStart) || (point >= vEnd)) continue;
11839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, point, &dof));
11849566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, point, &off));
1185846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1186846a3e8bSMatthew G. Knepley           tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1187846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1188846a3e8bSMatthew G. Knepley         }
1189846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1190846a3e8bSMatthew G. Knepley         if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1191846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];}
1192846a3e8bSMatthew G. Knepley         ++n;
1193846a3e8bSMatthew G. Knepley       }
1194846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {ccoords[d] /= n;}
11959566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1196846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11979566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11989566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]));
1199846a3e8bSMatthew G. Knepley       }
1200b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth%numColors];
1201b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
1202846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1203846a3e8bSMatthew G. Knepley         PetscInt val;
12049566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
1205846a3e8bSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
1206846a3e8bSMatthew G. Knepley       }
1207b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
12089566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c));
1209b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
12109566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
1211b7f6ffafSMatthew G. Knepley       } else {
12129566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank));
1213846a3e8bSMatthew G. Knepley       }
1214846a3e8bSMatthew G. Knepley     }
12159566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
1216b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1217b7f6ffafSMatthew G. Knepley       color = colors[depth%numColors];
12189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1223552f7358SJed Brown 
1224b7f6ffafSMatthew G. Knepley       color = colors[1%numColors];
12259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1230b7f6ffafSMatthew G. Knepley 
1231b7f6ffafSMatthew G. Knepley       color = colors[0%numColors];
12329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1237b7f6ffafSMatthew G. Knepley 
1238b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1239b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1240b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1241b7f6ffafSMatthew G. Knepley 
12429566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
12439566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1244b7f6ffafSMatthew G. Knepley         for (cp = 0; cp < coneSize; ++cp) {
12459566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank));
1246552f7358SJed Brown         }
12470588280cSMatthew G. Knepley       }
12480588280cSMatthew G. Knepley     }
12499566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
12509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
12519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
12529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name));
12539566063dSJacob Faibussowitsch     for (l = 0; l < numLabels;  ++l) PetscCall(PetscFree(names[l]));
12549566063dSJacob Faibussowitsch     for (c = 0; c < numColors;  ++c) PetscCall(PetscFree(colors[c]));
12559566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
12569566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
12579566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
12580f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
12590f7d6e4aSStefano Zampini     Vec                    cown,acown;
12600f7d6e4aSStefano Zampini     VecScatter             sct;
12610f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
12620f7d6e4aSStefano Zampini     IS                     gid,acis;
12630f7d6e4aSStefano Zampini     MPI_Comm               comm,ncomm = MPI_COMM_NULL;
12640f7d6e4aSStefano Zampini     MPI_Group              ggroup,ngroup;
12650f7d6e4aSStefano Zampini     PetscScalar            *array,nid;
12660f7d6e4aSStefano Zampini     const PetscInt         *idxs;
12670f7d6e4aSStefano Zampini     PetscInt               *idxs2,*start,*adjacency,*work;
12680f7d6e4aSStefano Zampini     PetscInt64             lm[3],gm[3];
12690f7d6e4aSStefano Zampini     PetscInt               i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight;
12700f7d6e4aSStefano Zampini     PetscMPIInt            d1,d2,rank;
12710f7d6e4aSStefano Zampini 
12729566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
12739566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
1274b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
12759566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm));
12760f7d6e4aSStefano Zampini #endif
12770f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
12789566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm,&ggroup));
12799566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm,&ngroup));
12800f7d6e4aSStefano Zampini       d1   = 0;
12819566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2));
12820f7d6e4aSStefano Zampini       nid  = d2;
12839566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
12849566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
12859566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
12860f7d6e4aSStefano Zampini     } else nid = 0.0;
12870f7d6e4aSStefano Zampini 
12880f7d6e4aSStefano Zampini     /* Get connectivity */
12899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight));
12909566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid));
12910f7d6e4aSStefano Zampini 
12920f7d6e4aSStefano Zampini     /* filter overlapped local cells */
12939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd));
12949566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid,&idxs));
12959566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid,&cum));
12969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&idxs2));
12970f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
12980f7d6e4aSStefano Zampini       if (idxs[c-cStart] < 0) continue;
12990f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c-cStart];
13000f7d6e4aSStefano Zampini     }
13019566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid,&idxs));
13022c71b3e2SJacob Faibussowitsch     PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum);
13039566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13049566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid));
13050f7d6e4aSStefano Zampini 
13060f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13079566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis));
13089566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown));
13099566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown));
13109566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown,&array));
13110f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13129566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown,&array));
13139566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct));
13149566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13159566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13179566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13189566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13190f7d6e4aSStefano Zampini 
13200f7d6e4aSStefano Zampini     /* compute edgeCut */
13210f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]);
13229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&work));
13239566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l));
13249566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH));
13259566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13269566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown,&array));
13270f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13280f7d6e4aSStefano Zampini       PetscInt totl;
13290f7d6e4aSStefano Zampini 
13300f7d6e4aSStefano Zampini       totl = start[c+1]-start[c];
13319566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work));
13320f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13330f7d6e4aSStefano Zampini         if (work[i] < 0) {
13340f7d6e4aSStefano Zampini           ect  += 1;
13350f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13360f7d6e4aSStefano Zampini         }
13370f7d6e4aSStefano Zampini       }
13380f7d6e4aSStefano Zampini     }
13399566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
13409566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown,&array));
13410f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
13420f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13439566063dSJacob Faibussowitsch     PetscCallMPI(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm));
13449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]));
13450f7d6e4aSStefano Zampini     lm[0] = ect; /* edgeCut */
13460f7d6e4aSStefano Zampini     lm[1] = ectn; /* node-aware edgeCut */
13470f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
13489566063dSJacob Faibussowitsch     PetscCallMPI(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm));
13499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]));
1350b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
13519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.));
13520f7d6e4aSStefano Zampini #else
13539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0));
13540f7d6e4aSStefano Zampini #endif
13559566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
13569566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
13579566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
13589566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1359552f7358SJed Brown   } else {
1360412e9a14SMatthew G. Knepley     const char    *name;
1361d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1362412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1363d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1364ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
13659318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1366412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1367412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1368552f7358SJed Brown 
13699566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
13709566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
13719566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
13729566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
13739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13749566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
13759566063dSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
13769566063dSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s"));
13779566063dSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight));
13789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
13799566063dSJacob Faibussowitsch     PetscCallMPI(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
13809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1381d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
13829566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
13839566063dSJacob Faibussowitsch     else                PetscCall(PetscCalloc3(3,    &sizes, 3,    &hybsizes, 3,    &ghostsizes));
1384412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1385412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1386412e9a14SMatthew G. Knepley 
13879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
13889566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1389412e9a14SMatthew G. Knepley       ict  = ct0;
13909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1391412e9a14SMatthew G. Knepley       ct0  = (DMPolytopeType) ict;
1392412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1393412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1394412e9a14SMatthew G. Knepley 
13959566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1396412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1397412e9a14SMatthew G. Knepley         else           ++Nc[1];
1398412e9a14SMatthew G. Knepley       }
1399ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14009566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm));
14019566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14029566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
14039566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %D-cells per rank:", (depth == 1) && d ? dim : d));
1404834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1405dd400576SPatrick Sanan           if (rank == 0) {
14069566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]));
14079566063dSJacob Faibussowitsch             if (hybsizes[p]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]));
14089566063dSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]));
1409834065abSMatthew G. Knepley           }
1410cbb7f117SMark Adams         }
1411ca7bf7eeSMatthew G. Knepley       } else {
1412ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1413ca7bf7eeSMatthew G. Knepley 
1414ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1];
14159566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
1416ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1];
14179566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1418ca7bf7eeSMatthew G. Knepley         if (d == depth) {
1419ca7bf7eeSMatthew G. Knepley           locMinMax[0] = gcNum; locMinMax[1] = gcNum;
14209566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1421ca7bf7eeSMatthew G. Knepley         }
14229566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d));
14239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14249566063dSJacob Faibussowitsch         if (hybsizes[0]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14259566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1426ca7bf7eeSMatthew G. Knepley       }
14279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1428552f7358SJed Brown     }
14299566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14309318fe57SMatthew G. Knepley     {
14319318fe57SMatthew G. Knepley       const PetscReal      *maxCell;
14329318fe57SMatthew G. Knepley       const PetscReal      *L;
14339318fe57SMatthew G. Knepley       const DMBoundaryType *bd;
14349318fe57SMatthew G. Knepley       PetscBool             per, localized;
14359318fe57SMatthew G. Knepley 
14369566063dSJacob Faibussowitsch       PetscCall(DMGetPeriodicity(dm, &per, &maxCell, &L, &bd));
14379566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
14389318fe57SMatthew G. Knepley       if (per) {
14399566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh ("));
14409566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14419318fe57SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
14429566063dSJacob Faibussowitsch           if (bd && d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
14439566063dSJacob Faibussowitsch           if (bd)    PetscCall(PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]));
14449318fe57SMatthew G. Knepley         }
14459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized"));
14469566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14479318fe57SMatthew G. Knepley       }
14489318fe57SMatthew G. Knepley     }
14499566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
14509566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1451a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1452a57dd577SMatthew G Knepley       DMLabel         label;
1453a57dd577SMatthew G Knepley       const char     *name;
1454a57dd577SMatthew G Knepley       IS              valueIS;
1455a57dd577SMatthew G Knepley       const PetscInt *values;
1456a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1457a57dd577SMatthew G Knepley 
14589566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
14599566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
14609566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
14619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %D strata with value/size (", name, numValues));
14629566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
14639566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
14649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1465a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1466a57dd577SMatthew G Knepley         PetscInt size;
1467a57dd577SMatthew G Knepley 
14689566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
14699566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
14709566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size));
1471a57dd577SMatthew G Knepley       }
14729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
14739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14749566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
14759566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1476a57dd577SMatthew G Knepley     }
1477c1cad2e7SMatthew G. Knepley     {
1478c1cad2e7SMatthew G. Knepley       char    **labelNames;
1479c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1480c1cad2e7SMatthew G. Knepley       PetscBool flg;
1481c1cad2e7SMatthew G. Knepley 
14829566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
14839566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1484c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1485c1cad2e7SMatthew G. Knepley         DMLabel label;
1486c1cad2e7SMatthew G. Knepley 
14879566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1488c1cad2e7SMatthew G. Knepley         if (flg) {
14899566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
14909566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1491c1cad2e7SMatthew G. Knepley         }
14929566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1493c1cad2e7SMatthew G. Knepley       }
14949566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1495c1cad2e7SMatthew G. Knepley     }
149634aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
149734aa8a36SMatthew G. Knepley     if (dm->Nf) {
149834aa8a36SMatthew G. Knepley       PetscInt f;
149934aa8a36SMatthew G. Knepley 
150034aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
150134aa8a36SMatthew G. Knepley         const char *name;
150234aa8a36SMatthew G. Knepley 
15039566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15049566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15059566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15069566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
150734aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15089566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15099566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
151034aa8a36SMatthew G. Knepley         } else {
15119566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15129566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
151334aa8a36SMatthew G. Knepley         }
15149566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
151534aa8a36SMatthew G. Knepley       }
151634aa8a36SMatthew G. Knepley     }
15179566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15188e7ff633SMatthew G. Knepley     if (cdm) {
15199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15209566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15228e7ff633SMatthew G. Knepley     }
1523552f7358SJed Brown   }
1524552f7358SJed Brown   PetscFunctionReturn(0);
1525552f7358SJed Brown }
1526552f7358SJed Brown 
1527e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1528e5c487bfSMatthew G. Knepley {
1529e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1530e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1531a12d352dSMatthew G. Knepley   PetscInt       cdim;
1532e5c487bfSMatthew G. Knepley 
1533e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
15349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
15359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
15369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1537e5c487bfSMatthew G. Knepley   switch (ct) {
1538a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1539a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1540a12d352dSMatthew G. Knepley     switch (cdim) {
1541a12d352dSMatthew G. Knepley     case 1:
1542a12d352dSMatthew G. Knepley     {
1543a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1544a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1545a12d352dSMatthew G. Knepley 
15469566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y,    PetscRealPart(coords[1]), y,    PETSC_DRAW_BLACK));
15479566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK));
15489566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK));
1549a12d352dSMatthew G. Knepley     }
1550a12d352dSMatthew G. Knepley     break;
1551a12d352dSMatthew G. Knepley     case 2:
1552a12d352dSMatthew G. Knepley     {
1553a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1554a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1555a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1/PetscSqrtReal(dx*dx + dy*dy);
1556a12d352dSMatthew G. Knepley 
15579566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15589566063dSJacob 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));
15599566063dSJacob 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));
1560a12d352dSMatthew G. Knepley     }
1561a12d352dSMatthew G. Knepley     break;
156298921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %D", cdim);
1563a12d352dSMatthew G. Knepley     }
1564a12d352dSMatthew G. Knepley     break;
1565e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
15669566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1567e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1568e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15695f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15709566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15719566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15729566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1573e5c487bfSMatthew G. Knepley     break;
1574e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
15759566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1576e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1577e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15785f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15799566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]),
1580e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1581e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15825f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15839566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15849566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15859566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
15869566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1587e5c487bfSMatthew G. Knepley     break;
158898921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1589e5c487bfSMatthew G. Knepley   }
1590e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1591e5c487bfSMatthew G. Knepley }
1592e5c487bfSMatthew G. Knepley 
1593e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1594e5c487bfSMatthew G. Knepley {
1595e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1596e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1597e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1598e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1599e5c487bfSMatthew G. Knepley 
1600e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
16029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1603e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2;
1604e5c487bfSMatthew G. Knepley   switch (ct) {
1605e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1606e5c487bfSMatthew G. Knepley     {
1607e5c487bfSMatthew G. Knepley       PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1608e5c487bfSMatthew G. Knepley 
1609e5c487bfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;}
1610e5c487bfSMatthew G. Knepley       for (e = 0; e < 3; ++e) {
1611e5c487bfSMatthew G. Knepley         refCoords[0] = refVertices[e*2+0];
1612e5c487bfSMatthew G. Knepley         refCoords[1] = refVertices[e*2+1];
1613e5c487bfSMatthew G. Knepley         for (d = 1; d <= edgeDiv; ++d) {
1614e5c487bfSMatthew G. Knepley           refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv;
1615e5c487bfSMatthew G. Knepley           refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv;
1616e5c487bfSMatthew G. Knepley         }
16179566063dSJacob Faibussowitsch         PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords));
1618e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
16199566063dSJacob 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));
16209566063dSJacob 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));
1621e5c487bfSMatthew G. Knepley         }
1622e5c487bfSMatthew G. Knepley       }
1623e5c487bfSMatthew G. Knepley     }
1624e5c487bfSMatthew G. Knepley     break;
162598921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1626e5c487bfSMatthew G. Knepley   }
1627e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1628e5c487bfSMatthew G. Knepley }
1629e5c487bfSMatthew G. Knepley 
16307cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1631e412dcbdSMatthew G. Knepley {
1632e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1633e412dcbdSMatthew G. Knepley   DM                 cdm;
1634e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1635e412dcbdSMatthew G. Knepley   Vec                coordinates;
1636e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
163729494db1SLisandro Dalcin   PetscReal          xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1638e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1639e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1640e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1641e412dcbdSMatthew G. Knepley 
1642e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
16439566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
16442c71b3e2SJacob Faibussowitsch   PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim);
16459566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
16469566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords));
16479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
16489566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
16499566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
16509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1652e412dcbdSMatthew G. Knepley 
16539566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16549566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1655e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
16569566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1657e412dcbdSMatthew G. Knepley 
16589566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
16599566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1660e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
16610c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
16620c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
1663e412dcbdSMatthew G. Knepley   }
16649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
16659566063dSJacob Faibussowitsch   PetscCallMPI(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm)));
16669566063dSJacob Faibussowitsch   PetscCallMPI(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm)));
16679566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
16689566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1669e412dcbdSMatthew G. Knepley 
1670cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1671cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1672ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1673cf3064d3SMatthew G. Knepley 
16749566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
1675e5c487bfSMatthew G. Knepley     if (drawAffine) {
16769566063dSJacob Faibussowitsch       PetscCall(DMPlexDrawCell(dm, draw, c, coords));
1677e5c487bfSMatthew G. Knepley     } else {
16789566063dSJacob Faibussowitsch       PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1679cf3064d3SMatthew G. Knepley     }
16809566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1681cf3064d3SMatthew G. Knepley   }
16829566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
16839566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
16849566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
16859566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1686e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1687e412dcbdSMatthew G. Knepley }
1688e412dcbdSMatthew G. Knepley 
16891e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
16901e50132fSMatthew G. Knepley #include <exodusII.h>
16916823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
16921e50132fSMatthew G. Knepley #endif
16931e50132fSMatthew G. Knepley 
1694552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1695552f7358SJed Brown {
16961e50132fSMatthew G. Knepley   PetscBool      iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus;
1697002a2709SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
1698552f7358SJed Brown 
1699552f7358SJed Brown   PetscFunctionBegin;
1700552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1701552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii));
17039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
17049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
17059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
17069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
17079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus));
1708552f7358SJed Brown   if (iascii) {
17098135c375SStefano Zampini     PetscViewerFormat format;
17109566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17118135c375SStefano Zampini     if (format == PETSC_VIEWER_ASCII_GLVIS) {
17129566063dSJacob Faibussowitsch       PetscCall(DMPlexView_GLVis(dm, viewer));
17138135c375SStefano Zampini     } else {
17149566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(dm, viewer));
17158135c375SStefano Zampini     }
1716c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1717c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17189566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1719c6ccd67eSMatthew G. Knepley #else
1720c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1721552f7358SJed Brown #endif
1722e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17239566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer));
1724e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17259566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17268135c375SStefano Zampini   } else if (isglvis) {
17279566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17281e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17291e50132fSMatthew G. Knepley   } else if (isexodus) {
17306823f3c5SBlaise Bourdin /*
17316823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17326823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
17336823f3c5SBlaise Bourdin       with ID 1, containig all cells.
17346823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
17356823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
17366823f3c5SBlaise Bourdin     */
17376823f3c5SBlaise Bourdin     PetscInt numCS;
17389566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS));
17396823f3c5SBlaise Bourdin     if (!numCS) {
17401e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17419566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
17429566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17439566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
17446823f3c5SBlaise Bourdin     }
17459566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
17461e50132fSMatthew G. Knepley #endif
174762201deeSVaclav Hapla   } else {
174898921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1749fcf6c8fdSToby Isaac   }
1750cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
17519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg));
1752cb3ba0daSMatthew G. Knepley   if (flg) {
1753cb3ba0daSMatthew G. Knepley     Vec ranks;
17549566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
17559566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
17569566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1757cb3ba0daSMatthew G. Knepley   }
1758002a2709SMatthew G. Knepley   /* Optionally view a label */
17599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1760002a2709SMatthew G. Knepley   if (flg) {
1761002a2709SMatthew G. Knepley     DMLabel label;
1762002a2709SMatthew G. Knepley     Vec     val;
1763002a2709SMatthew G. Knepley 
17649566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
176528b400f6SJacob Faibussowitsch     PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
17669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
17679566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
17689566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1769002a2709SMatthew G. Knepley   }
1770552f7358SJed Brown   PetscFunctionReturn(0);
1771552f7358SJed Brown }
1772552f7358SJed Brown 
17737f96f51bSksagiyam /*@
17747f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
17757f96f51bSksagiyam 
17767f96f51bSksagiyam   Collective on DM
17777f96f51bSksagiyam 
17787f96f51bSksagiyam   Input Parameters:
17797f96f51bSksagiyam + dm     - The DM whose topology is to be saved
17807f96f51bSksagiyam - viewer - The PetscViewer for saving
17817f96f51bSksagiyam 
17827f96f51bSksagiyam   Level: advanced
17837f96f51bSksagiyam 
17847f96f51bSksagiyam .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad()
17857f96f51bSksagiyam @*/
17867f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
17877f96f51bSksagiyam {
17887f96f51bSksagiyam   PetscBool      ishdf5;
17897f96f51bSksagiyam 
17907f96f51bSksagiyam   PetscFunctionBegin;
17917f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17927f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
17949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0));
17957f96f51bSksagiyam   if (ishdf5) {
17967f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
17977f96f51bSksagiyam     PetscViewerFormat format;
17989566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17997f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18007f96f51bSksagiyam       IS globalPointNumbering;
18017f96f51bSksagiyam 
18029566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18039566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
180598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18067f96f51bSksagiyam #else
18077f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18087f96f51bSksagiyam #endif
18097f96f51bSksagiyam   }
18109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0));
18117f96f51bSksagiyam   PetscFunctionReturn(0);
18127f96f51bSksagiyam }
18137f96f51bSksagiyam 
181477b8e257Sksagiyam /*@
181577b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
181677b8e257Sksagiyam 
181777b8e257Sksagiyam   Collective on DM
181877b8e257Sksagiyam 
181977b8e257Sksagiyam   Input Parameters:
182077b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
182177b8e257Sksagiyam - viewer - The PetscViewer for saving
182277b8e257Sksagiyam 
182377b8e257Sksagiyam   Level: advanced
182477b8e257Sksagiyam 
182577b8e257Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad()
182677b8e257Sksagiyam @*/
182777b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
182877b8e257Sksagiyam {
182977b8e257Sksagiyam   PetscBool      ishdf5;
183077b8e257Sksagiyam 
183177b8e257Sksagiyam   PetscFunctionBegin;
183277b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
183377b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0));
183677b8e257Sksagiyam   if (ishdf5) {
183777b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
183877b8e257Sksagiyam     PetscViewerFormat format;
18399566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
184077b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18419566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
184298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
184377b8e257Sksagiyam #else
184477b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
184577b8e257Sksagiyam #endif
184677b8e257Sksagiyam   }
18479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0));
184877b8e257Sksagiyam   PetscFunctionReturn(0);
184977b8e257Sksagiyam }
185077b8e257Sksagiyam 
1851bd6565f1Sksagiyam /*@
1852bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1853bd6565f1Sksagiyam 
1854bd6565f1Sksagiyam   Collective on DM
1855bd6565f1Sksagiyam 
1856bd6565f1Sksagiyam   Input Parameters:
1857bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1858bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1859bd6565f1Sksagiyam 
1860bd6565f1Sksagiyam   Level: advanced
1861bd6565f1Sksagiyam 
1862bd6565f1Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad()
1863bd6565f1Sksagiyam @*/
1864bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1865bd6565f1Sksagiyam {
1866bd6565f1Sksagiyam   PetscBool      ishdf5;
1867bd6565f1Sksagiyam 
1868bd6565f1Sksagiyam   PetscFunctionBegin;
1869bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1870bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0));
1873bd6565f1Sksagiyam   if (ishdf5) {
1874bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1875bd6565f1Sksagiyam     IS                globalPointNumbering;
1876bd6565f1Sksagiyam     PetscViewerFormat format;
1877bd6565f1Sksagiyam 
18789566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1879bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18809566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18819566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
18829566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
188398921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1884bd6565f1Sksagiyam #else
1885bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1886bd6565f1Sksagiyam #endif
1887bd6565f1Sksagiyam   }
18889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0));
1889bd6565f1Sksagiyam   PetscFunctionReturn(0);
1890bd6565f1Sksagiyam }
1891bd6565f1Sksagiyam 
1892021affd3Sksagiyam /*@
1893021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1894021affd3Sksagiyam 
1895021affd3Sksagiyam   Collective on DM
1896021affd3Sksagiyam 
1897021affd3Sksagiyam   Input Parameters:
1898021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1899021affd3Sksagiyam . viewer     - The PetscViewer for saving
1900021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1901021affd3Sksagiyam 
1902021affd3Sksagiyam   Level: advanced
1903021affd3Sksagiyam 
1904021affd3Sksagiyam   Notes:
1905021affd3Sksagiyam   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.
1906021affd3Sksagiyam 
1907021affd3Sksagiyam   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.
1908021affd3Sksagiyam 
1909021affd3Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad()
1910021affd3Sksagiyam @*/
1911021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1912021affd3Sksagiyam {
1913021affd3Sksagiyam   PetscBool      ishdf5;
1914021affd3Sksagiyam 
1915021affd3Sksagiyam   PetscFunctionBegin;
1916021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1917021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1918021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
19209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0));
1921021affd3Sksagiyam   if (ishdf5) {
1922021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19239566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1924021affd3Sksagiyam #else
1925021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1926021affd3Sksagiyam #endif
1927021affd3Sksagiyam   }
19289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0));
1929021affd3Sksagiyam   PetscFunctionReturn(0);
1930021affd3Sksagiyam }
1931021affd3Sksagiyam 
19323e97647fSksagiyam /*@
19333e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
19343e97647fSksagiyam 
19353e97647fSksagiyam   Collective on DM
19363e97647fSksagiyam 
19373e97647fSksagiyam   Input Parameters:
19383e97647fSksagiyam + dm        - The DM that represents the topology
19393e97647fSksagiyam . viewer    - The PetscViewer to save data with
19403e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
19413e97647fSksagiyam - vec       - The global vector to be saved
19423e97647fSksagiyam 
19433e97647fSksagiyam   Level: advanced
19443e97647fSksagiyam 
19453e97647fSksagiyam   Notes:
19463e97647fSksagiyam   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.
19473e97647fSksagiyam 
19483e97647fSksagiyam   Typical calling sequence
19493e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19503e97647fSksagiyam $       DMSetType(dm, DMPLEX);
19513e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19523e97647fSksagiyam $       DMClone(dm, &sectiondm);
19533e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19543e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
19553e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
19563e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
19573e97647fSksagiyam $       PetscSectionSetUp(section);
19583e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
19593e97647fSksagiyam $       PetscSectionDestroy(&section);
19603e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
19613e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19623e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
19633e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
19643e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
19653e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
19663e97647fSksagiyam $       DMDestroy(&sectiondm);
19673e97647fSksagiyam $       DMDestroy(&dm);
19683e97647fSksagiyam 
19693e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad()
19703e97647fSksagiyam @*/
19713e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
19723e97647fSksagiyam {
19733e97647fSksagiyam   PetscBool       ishdf5;
19743e97647fSksagiyam 
19753e97647fSksagiyam   PetscFunctionBegin;
19763e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19773e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19783e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19793e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
19803e97647fSksagiyam   /* Check consistency */
19813e97647fSksagiyam   {
19823e97647fSksagiyam     PetscSection  section;
19833e97647fSksagiyam     PetscBool     includesConstraints;
19843e97647fSksagiyam     PetscInt      m, m1;
19853e97647fSksagiyam 
19869566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
19879566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
19889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
19899566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
19909566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
19912c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m);
19923e97647fSksagiyam   }
19939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0));
19953e97647fSksagiyam   if (ishdf5) {
19963e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
19979566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
19983e97647fSksagiyam #else
19993e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20003e97647fSksagiyam #endif
20013e97647fSksagiyam   }
20029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0));
20033e97647fSksagiyam   PetscFunctionReturn(0);
20043e97647fSksagiyam }
20053e97647fSksagiyam 
20063e97647fSksagiyam /*@
20073e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20083e97647fSksagiyam 
20093e97647fSksagiyam   Collective on DM
20103e97647fSksagiyam 
20113e97647fSksagiyam   Input Parameters:
20123e97647fSksagiyam + dm        - The DM that represents the topology
20133e97647fSksagiyam . viewer    - The PetscViewer to save data with
20143e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
20153e97647fSksagiyam - vec       - The local vector to be saved
20163e97647fSksagiyam 
20173e97647fSksagiyam   Level: advanced
20183e97647fSksagiyam 
20193e97647fSksagiyam   Notes:
20203e97647fSksagiyam   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.
20213e97647fSksagiyam 
20223e97647fSksagiyam   Typical calling sequence
20233e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
20243e97647fSksagiyam $       DMSetType(dm, DMPLEX);
20253e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
20263e97647fSksagiyam $       DMClone(dm, &sectiondm);
20273e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
20283e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
20293e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
20303e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
20313e97647fSksagiyam $       PetscSectionSetUp(section);
20323e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
20333e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
20343e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
20353e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
20363e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
20373e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
20383e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
20393e97647fSksagiyam $       DMDestroy(&sectiondm);
20403e97647fSksagiyam $       DMDestroy(&dm);
20413e97647fSksagiyam 
20423e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad()
20433e97647fSksagiyam @*/
20443e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
20453e97647fSksagiyam {
20463e97647fSksagiyam   PetscBool       ishdf5;
20473e97647fSksagiyam 
20483e97647fSksagiyam   PetscFunctionBegin;
20493e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20503e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20513e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20523e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20533e97647fSksagiyam   /* Check consistency */
20543e97647fSksagiyam   {
20553e97647fSksagiyam     PetscSection  section;
20563e97647fSksagiyam     PetscBool     includesConstraints;
20573e97647fSksagiyam     PetscInt      m, m1;
20583e97647fSksagiyam 
20599566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20609566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
20619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20629566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20639566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
20642c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m);
20653e97647fSksagiyam   }
20669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0));
20683e97647fSksagiyam   if (ishdf5) {
20693e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20709566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20713e97647fSksagiyam #else
20723e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20733e97647fSksagiyam #endif
20743e97647fSksagiyam   }
20759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0));
20763e97647fSksagiyam   PetscFunctionReturn(0);
20773e97647fSksagiyam }
20783e97647fSksagiyam 
20792c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
20802c40f234SMatthew G. Knepley {
2081d4f5a9a0SVaclav Hapla   PetscBool      ishdf5;
20822c40f234SMatthew G. Knepley 
20832c40f234SMatthew G. Knepley   PetscFunctionBegin;
20842c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20852c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5));
2087d4f5a9a0SVaclav Hapla   if (ishdf5) {
20882c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
20899c48423bSVaclav Hapla     PetscViewerFormat format;
20909566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20919c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
20929566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2093509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20949566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
209598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2096b458e8f1SJose E. Roman     PetscFunctionReturn(0);
20972c40f234SMatthew G. Knepley #else
20982c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2099552f7358SJed Brown #endif
210098921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2101552f7358SJed Brown }
2102552f7358SJed Brown 
2103ea8e1828Sksagiyam /*@
2104ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
2105ea8e1828Sksagiyam 
2106ea8e1828Sksagiyam   Collective on DM
2107ea8e1828Sksagiyam 
2108ea8e1828Sksagiyam   Input Parameters:
2109ea8e1828Sksagiyam + dm     - The DM into which the topology is loaded
2110ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology
2111ea8e1828Sksagiyam 
2112dec9e869Sksagiyam   Output Parameters:
2113f84dd6b4Sksagiyam . 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
2114dec9e869Sksagiyam 
2115ea8e1828Sksagiyam   Level: advanced
2116ea8e1828Sksagiyam 
2117b08ad5deSksagiyam .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
2118ea8e1828Sksagiyam @*/
2119f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2120ea8e1828Sksagiyam {
2121ea8e1828Sksagiyam   PetscBool      ishdf5;
2122ea8e1828Sksagiyam 
2123ea8e1828Sksagiyam   PetscFunctionBegin;
2124ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2125ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2126f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
21279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0));
2129ea8e1828Sksagiyam   if (ishdf5) {
2130ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2131ea8e1828Sksagiyam     PetscViewerFormat format;
21329566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2133ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21349566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
213598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2136ea8e1828Sksagiyam #else
2137ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2138ea8e1828Sksagiyam #endif
2139ea8e1828Sksagiyam   }
21409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0));
2141ea8e1828Sksagiyam   PetscFunctionReturn(0);
2142ea8e1828Sksagiyam }
2143ea8e1828Sksagiyam 
21443e701f1cSksagiyam /*@
21453e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
21463e701f1cSksagiyam 
21473e701f1cSksagiyam   Collective on DM
21483e701f1cSksagiyam 
21493e701f1cSksagiyam   Input Parameters:
21503e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
2151c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates
2152c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
21533e701f1cSksagiyam 
21543e701f1cSksagiyam   Level: advanced
21553e701f1cSksagiyam 
2156b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
21573e701f1cSksagiyam @*/
2158c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
21593e701f1cSksagiyam {
21603e701f1cSksagiyam   PetscBool      ishdf5;
21613e701f1cSksagiyam 
21623e701f1cSksagiyam   PetscFunctionBegin;
21633e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21643e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2165c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
21669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21683e701f1cSksagiyam   if (ishdf5) {
21693e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
21703e701f1cSksagiyam     PetscViewerFormat format;
21719566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21723e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21739566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
217498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21753e701f1cSksagiyam #else
21763e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21773e701f1cSksagiyam #endif
21783e701f1cSksagiyam   }
21799566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21803e701f1cSksagiyam   PetscFunctionReturn(0);
21813e701f1cSksagiyam }
21823e701f1cSksagiyam 
2183b08ad5deSksagiyam /*@
2184b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
2185b08ad5deSksagiyam 
2186b08ad5deSksagiyam   Collective on DM
2187b08ad5deSksagiyam 
2188b08ad5deSksagiyam   Input Parameters:
2189b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
2190e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels
2191e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2192b08ad5deSksagiyam 
2193b08ad5deSksagiyam   Level: advanced
2194b08ad5deSksagiyam 
2195e6368b79SVaclav Hapla   Notes:
2196e6368b79SVaclav Hapla   The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs.
2197e6368b79SVaclav Hapla 
2198b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
2199b08ad5deSksagiyam @*/
2200e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2201b08ad5deSksagiyam {
2202b08ad5deSksagiyam   PetscBool      ishdf5;
2203b08ad5deSksagiyam 
2204b08ad5deSksagiyam   PetscFunctionBegin;
2205b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2206b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2207e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
22099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0));
2210b08ad5deSksagiyam   if (ishdf5) {
2211b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2212b08ad5deSksagiyam     PetscViewerFormat format;
2213b08ad5deSksagiyam 
22149566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2215b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22169566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
221798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2218b08ad5deSksagiyam #else
2219b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2220b08ad5deSksagiyam #endif
2221b08ad5deSksagiyam   }
22229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0));
2223b08ad5deSksagiyam   PetscFunctionReturn(0);
2224b08ad5deSksagiyam }
2225b08ad5deSksagiyam 
2226f84dd6b4Sksagiyam /*@
2227f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
2228f84dd6b4Sksagiyam 
2229f84dd6b4Sksagiyam   Collective on DM
2230f84dd6b4Sksagiyam 
2231f84dd6b4Sksagiyam   Input Parameters:
2232f84dd6b4Sksagiyam + dm          - The DM that represents the topology
2233f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
2234f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
2235f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2236f84dd6b4Sksagiyam 
2237f84dd6b4Sksagiyam   Output Parameters
2238f84dd6b4Sksagiyam + 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)
2239f84dd6b4Sksagiyam - 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)
2240f84dd6b4Sksagiyam 
2241f84dd6b4Sksagiyam   Level: advanced
2242f84dd6b4Sksagiyam 
2243f84dd6b4Sksagiyam   Notes:
2244f84dd6b4Sksagiyam   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.
2245f84dd6b4Sksagiyam 
2246f84dd6b4Sksagiyam   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.
2247f84dd6b4Sksagiyam 
2248f84dd6b4Sksagiyam   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.
2249f84dd6b4Sksagiyam 
2250f84dd6b4Sksagiyam   Example using 2 processes:
2251f84dd6b4Sksagiyam $  NX (number of points on dm): 4
2252f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
2253f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
2254f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
2255f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
2256f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
2257f84dd6b4Sksagiyam $
2258f84dd6b4Sksagiyam $                                     rank 0    rank 1
2259f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2260f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2261f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2262f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2263f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2264f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2265f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
2266f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2267f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2268f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2269f84dd6b4Sksagiyam $
2270f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2271f84dd6b4Sksagiyam 
2272f84dd6b4Sksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView()
2273f84dd6b4Sksagiyam @*/
2274f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2275f84dd6b4Sksagiyam {
2276f84dd6b4Sksagiyam   PetscBool      ishdf5;
2277f84dd6b4Sksagiyam 
2278f84dd6b4Sksagiyam   PetscFunctionBegin;
2279f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2280f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2281f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2282f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2283f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2284f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
22859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
22869566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0));
2287f84dd6b4Sksagiyam   if (ishdf5) {
2288f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
22899566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2290f84dd6b4Sksagiyam #else
2291f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2292f84dd6b4Sksagiyam #endif
2293f84dd6b4Sksagiyam   }
22949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0));
2295f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2296f84dd6b4Sksagiyam }
2297f84dd6b4Sksagiyam 
22988be3dfe1Sksagiyam /*@
22998be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23008be3dfe1Sksagiyam 
23018be3dfe1Sksagiyam   Collective on DM
23028be3dfe1Sksagiyam 
23038be3dfe1Sksagiyam   Input Parameters:
23048be3dfe1Sksagiyam + dm        - The DM that represents the topology
23058be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23068be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
23078be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23088be3dfe1Sksagiyam - vec       - The global vector to set values of
23098be3dfe1Sksagiyam 
23108be3dfe1Sksagiyam   Level: advanced
23118be3dfe1Sksagiyam 
23128be3dfe1Sksagiyam   Notes:
23138be3dfe1Sksagiyam   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.
23148be3dfe1Sksagiyam 
23158be3dfe1Sksagiyam   Typical calling sequence
23168be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23178be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23188be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23198be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23208be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23218be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23228be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
23238be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
23248be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23258be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
23268be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
23278be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
23288be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
23298be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
23308be3dfe1Sksagiyam $       DMDestroy(&dm);
23318be3dfe1Sksagiyam 
23328be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView()
23338be3dfe1Sksagiyam @*/
23348be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
23358be3dfe1Sksagiyam {
23368be3dfe1Sksagiyam   PetscBool       ishdf5;
23378be3dfe1Sksagiyam 
23388be3dfe1Sksagiyam   PetscFunctionBegin;
23398be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23408be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23418be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
23428be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
23438be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
23448be3dfe1Sksagiyam   /* Check consistency */
23458be3dfe1Sksagiyam   {
23468be3dfe1Sksagiyam     PetscSection  section;
23478be3dfe1Sksagiyam     PetscBool     includesConstraints;
23488be3dfe1Sksagiyam     PetscInt      m, m1;
23498be3dfe1Sksagiyam 
23509566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
23519566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
23529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
23539566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
23549566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
23552c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m);
23568be3dfe1Sksagiyam   }
23579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
23589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23598be3dfe1Sksagiyam   if (ishdf5) {
23608be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
23619566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
23628be3dfe1Sksagiyam #else
23638be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23648be3dfe1Sksagiyam #endif
23658be3dfe1Sksagiyam   }
23669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23678be3dfe1Sksagiyam   PetscFunctionReturn(0);
23688be3dfe1Sksagiyam }
23698be3dfe1Sksagiyam 
23708be3dfe1Sksagiyam /*@
23718be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
23728be3dfe1Sksagiyam 
23738be3dfe1Sksagiyam   Collective on DM
23748be3dfe1Sksagiyam 
23758be3dfe1Sksagiyam   Input Parameters:
23768be3dfe1Sksagiyam + dm        - The DM that represents the topology
23778be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23788be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined
23798be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23808be3dfe1Sksagiyam - vec       - The local vector to set values of
23818be3dfe1Sksagiyam 
23828be3dfe1Sksagiyam   Level: advanced
23838be3dfe1Sksagiyam 
23848be3dfe1Sksagiyam   Notes:
23858be3dfe1Sksagiyam   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.
23868be3dfe1Sksagiyam 
23878be3dfe1Sksagiyam   Typical calling sequence
23888be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23898be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23908be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23918be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23928be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23938be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23948be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
23958be3dfe1Sksagiyam $       DMGetLocalVector(sectiondm, &vec);
23968be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23978be3dfe1Sksagiyam $       DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
23988be3dfe1Sksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
23998be3dfe1Sksagiyam $       PetscSFDestroy(&lsf);
24008be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
24018be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
24028be3dfe1Sksagiyam $       DMDestroy(&dm);
24038be3dfe1Sksagiyam 
24048be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView()
24058be3dfe1Sksagiyam @*/
24068be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
24078be3dfe1Sksagiyam {
24088be3dfe1Sksagiyam   PetscBool       ishdf5;
24098be3dfe1Sksagiyam 
24108be3dfe1Sksagiyam   PetscFunctionBegin;
24118be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24128be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24138be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24148be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24158be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24168be3dfe1Sksagiyam   /* Check consistency */
24178be3dfe1Sksagiyam   {
24188be3dfe1Sksagiyam     PetscSection  section;
24198be3dfe1Sksagiyam     PetscBool     includesConstraints;
24208be3dfe1Sksagiyam     PetscInt      m, m1;
24218be3dfe1Sksagiyam 
24229566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24239566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
24249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24259566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24269566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
24272c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m);
24288be3dfe1Sksagiyam   }
24299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
24309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24318be3dfe1Sksagiyam   if (ishdf5) {
24328be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24339566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24348be3dfe1Sksagiyam #else
24358be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24368be3dfe1Sksagiyam #endif
24378be3dfe1Sksagiyam   }
24389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24398be3dfe1Sksagiyam   PetscFunctionReturn(0);
24408be3dfe1Sksagiyam }
24418be3dfe1Sksagiyam 
2442552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
2443552f7358SJed Brown {
2444552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2445552f7358SJed Brown 
2446552f7358SJed Brown   PetscFunctionBegin;
24479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL));
24489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL));
24499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL));
24509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL));
24510d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
24529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
24539566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
24549566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
24559566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
24569566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
24579566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
24589566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
24599566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
24609566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
24619566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
24629566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
24639566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
24649566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
24659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
24669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
24679566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
24689566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
24699566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
24709566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
24719566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
24729566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
24739566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
24749566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
24759566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
24769566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
24779566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2478552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
24799566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
2480552f7358SJed Brown   PetscFunctionReturn(0);
2481552f7358SJed Brown }
2482552f7358SJed Brown 
2483b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2484552f7358SJed Brown {
24858d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2486acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
2487552f7358SJed Brown   PetscInt               localSize;
2488837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2489b412c318SBarry Smith   MatType                mtype;
24901428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2491552f7358SJed Brown 
2492552f7358SJed Brown   PetscFunctionBegin;
24939566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2494b412c318SBarry Smith   mtype = dm->mattype;
24959566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
24969566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
24979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
24989566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
24999566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25009566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25019566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25029566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2503acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25049566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
25059566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25069566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25079566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25089566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25099566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25109566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25119566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2512552f7358SJed Brown   if (!isShell) {
2513837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
2514e432b41dSStefano Zampini     PetscInt  *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2];
2515fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2516552f7358SJed Brown 
25179566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm,&ltog));
25189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2519e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2520a9d99c84SMatthew G. Knepley       PetscInt bdof;
2521a9d99c84SMatthew G. Knepley 
25229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
25239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
25241d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof+1) : dof;
25251d17a0a3SMatthew G. Knepley       bdof = cdof && (dof-cdof) ? 1 : dof;
25261d17a0a3SMatthew G. Knepley       if (dof) {
25271d17a0a3SMatthew G. Knepley         if (bs < 0)          {bs = bdof;}
2528e432b41dSStefano Zampini         else if (bs != bdof) {bs = 1; break;}
2529552f7358SJed Brown       }
25302a28c762SMatthew G Knepley     }
25312a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2532e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2533e432b41dSStefano Zampini     bsLocal[1] = bs;
25349566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
2535e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2536e432b41dSStefano Zampini     else bs = bsMinMax[0];
25376fd5c86aSStefano Zampini     bs = PetscMax(1,bs);
25389566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J,ltog,ltog));
25390682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
25409566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
25419566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
25420682b8bbSJed Brown     } else {
25439566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu));
25449566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
25459566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2546552f7358SJed Brown     }
2547aa0f6e3cSJed Brown   }
25489566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
2549552f7358SJed Brown   PetscFunctionReturn(0);
2550552f7358SJed Brown }
2551552f7358SJed Brown 
25527cd05799SMatthew G. Knepley /*@
2553a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2554be36d101SStefano Zampini 
2555be36d101SStefano Zampini   Not collective
2556be36d101SStefano Zampini 
2557be36d101SStefano Zampini   Input Parameter:
2558be36d101SStefano Zampini . mesh - The DMPlex
2559be36d101SStefano Zampini 
2560be36d101SStefano Zampini   Output Parameters:
2561be36d101SStefano Zampini . subsection - The subdomain section
2562be36d101SStefano Zampini 
2563be36d101SStefano Zampini   Level: developer
2564be36d101SStefano Zampini 
2565be36d101SStefano Zampini .seealso:
25667cd05799SMatthew G. Knepley @*/
2567be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2568be36d101SStefano Zampini {
2569be36d101SStefano Zampini   DM_Plex       *mesh = (DM_Plex*) dm->data;
2570be36d101SStefano Zampini 
2571be36d101SStefano Zampini   PetscFunctionBegin;
2572be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2573be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2574be36d101SStefano Zampini     PetscSection section;
2575be36d101SStefano Zampini     PetscSF      sf;
2576be36d101SStefano Zampini 
25779566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf));
25789566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
25799566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection));
25809566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2581be36d101SStefano Zampini   }
2582be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2583be36d101SStefano Zampini   PetscFunctionReturn(0);
2584be36d101SStefano Zampini }
2585be36d101SStefano Zampini 
2586552f7358SJed Brown /*@
2587552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2588552f7358SJed Brown 
2589552f7358SJed Brown   Not collective
2590552f7358SJed Brown 
2591552f7358SJed Brown   Input Parameter:
2592552f7358SJed Brown . mesh - The DMPlex
2593552f7358SJed Brown 
2594552f7358SJed Brown   Output Parameters:
2595552f7358SJed Brown + pStart - The first mesh point
2596552f7358SJed Brown - pEnd   - The upper bound for mesh points
2597552f7358SJed Brown 
2598552f7358SJed Brown   Level: beginner
2599552f7358SJed Brown 
2600552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart()
2601552f7358SJed Brown @*/
2602552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2603552f7358SJed Brown {
2604552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2605552f7358SJed Brown 
2606552f7358SJed Brown   PetscFunctionBegin;
2607552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
2609552f7358SJed Brown   PetscFunctionReturn(0);
2610552f7358SJed Brown }
2611552f7358SJed Brown 
2612552f7358SJed Brown /*@
2613552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2614552f7358SJed Brown 
2615552f7358SJed Brown   Not collective
2616552f7358SJed Brown 
2617552f7358SJed Brown   Input Parameters:
2618552f7358SJed Brown + mesh - The DMPlex
2619552f7358SJed Brown . pStart - The first mesh point
2620552f7358SJed Brown - pEnd   - The upper bound for mesh points
2621552f7358SJed Brown 
2622552f7358SJed Brown   Output Parameters:
2623552f7358SJed Brown 
2624552f7358SJed Brown   Level: beginner
2625552f7358SJed Brown 
2626552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart()
2627552f7358SJed Brown @*/
2628552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2629552f7358SJed Brown {
2630552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2631552f7358SJed Brown 
2632552f7358SJed Brown   PetscFunctionBegin;
2633552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
26359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2636552f7358SJed Brown   PetscFunctionReturn(0);
2637552f7358SJed Brown }
2638552f7358SJed Brown 
2639552f7358SJed Brown /*@
2640eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2641552f7358SJed Brown 
2642552f7358SJed Brown   Not collective
2643552f7358SJed Brown 
2644552f7358SJed Brown   Input Parameters:
2645552f7358SJed Brown + mesh - The DMPlex
2646eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2647552f7358SJed Brown 
2648552f7358SJed Brown   Output Parameter:
2649552f7358SJed Brown . size - The cone size for point p
2650552f7358SJed Brown 
2651552f7358SJed Brown   Level: beginner
2652552f7358SJed Brown 
2653552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
2654552f7358SJed Brown @*/
2655552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2656552f7358SJed Brown {
2657552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2658552f7358SJed Brown 
2659552f7358SJed Brown   PetscFunctionBegin;
2660552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2661dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
26629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
2663552f7358SJed Brown   PetscFunctionReturn(0);
2664552f7358SJed Brown }
2665552f7358SJed Brown 
2666552f7358SJed Brown /*@
2667eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2668552f7358SJed Brown 
2669552f7358SJed Brown   Not collective
2670552f7358SJed Brown 
2671552f7358SJed Brown   Input Parameters:
2672552f7358SJed Brown + mesh - The DMPlex
2673eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2674552f7358SJed Brown - size - The cone size for point p
2675552f7358SJed Brown 
2676552f7358SJed Brown   Output Parameter:
2677552f7358SJed Brown 
2678552f7358SJed Brown   Note:
2679552f7358SJed Brown   This should be called after DMPlexSetChart().
2680552f7358SJed Brown 
2681552f7358SJed Brown   Level: beginner
2682552f7358SJed Brown 
2683552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart()
2684552f7358SJed Brown @*/
2685552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2686552f7358SJed Brown {
2687552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2688552f7358SJed Brown 
2689552f7358SJed Brown   PetscFunctionBegin;
2690552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26919566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
2692552f7358SJed Brown   PetscFunctionReturn(0);
2693552f7358SJed Brown }
2694552f7358SJed Brown 
2695f5a469b9SMatthew G. Knepley /*@
2696eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2697f5a469b9SMatthew G. Knepley 
2698f5a469b9SMatthew G. Knepley   Not collective
2699f5a469b9SMatthew G. Knepley 
2700f5a469b9SMatthew G. Knepley   Input Parameters:
2701f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2702eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2703f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2704f5a469b9SMatthew G. Knepley 
2705f5a469b9SMatthew G. Knepley   Output Parameter:
2706f5a469b9SMatthew G. Knepley 
2707f5a469b9SMatthew G. Knepley   Note:
2708f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2709f5a469b9SMatthew G. Knepley 
2710f5a469b9SMatthew G. Knepley   Level: beginner
2711f5a469b9SMatthew G. Knepley 
2712f5a469b9SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart()
2713f5a469b9SMatthew G. Knepley @*/
2714f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2715f5a469b9SMatthew G. Knepley {
2716f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2717f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2718f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27199566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(mesh->coneSection, p, size));
2720f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2721f5a469b9SMatthew G. Knepley }
2722f5a469b9SMatthew G. Knepley 
2723552f7358SJed Brown /*@C
2724eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2725552f7358SJed Brown 
2726552f7358SJed Brown   Not collective
2727552f7358SJed Brown 
2728552f7358SJed Brown   Input Parameters:
2729833c876bSVaclav Hapla + dm - The DMPlex
2730eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2731552f7358SJed Brown 
2732552f7358SJed Brown   Output Parameter:
2733552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2734552f7358SJed Brown 
2735552f7358SJed Brown   Level: beginner
2736552f7358SJed Brown 
27373813dfbdSMatthew G Knepley   Fortran Notes:
27383813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27393813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2740922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2741922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
27423813dfbdSMatthew G Knepley 
2743e45f02b0SMatthew G. Knepley .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart()
2744552f7358SJed Brown @*/
2745552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2746552f7358SJed Brown {
2747552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2748552f7358SJed Brown   PetscInt       off;
2749552f7358SJed Brown 
2750552f7358SJed Brown   PetscFunctionBegin;
2751552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2752552f7358SJed Brown   PetscValidPointer(cone, 3);
27539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2754552f7358SJed Brown   *cone = &mesh->cones[off];
2755552f7358SJed Brown   PetscFunctionReturn(0);
2756552f7358SJed Brown }
2757552f7358SJed Brown 
27580ce7577fSVaclav Hapla /*@C
27590ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
27600ce7577fSVaclav Hapla 
27610ce7577fSVaclav Hapla   Not collective
27620ce7577fSVaclav Hapla 
27630ce7577fSVaclav Hapla   Input Parameters:
27640ce7577fSVaclav Hapla + dm - The DMPlex
27650ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
27660ce7577fSVaclav Hapla 
2767d8d19677SJose E. Roman   Output Parameters:
27680ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
27690ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
27700ce7577fSVaclav Hapla 
27710ce7577fSVaclav Hapla   Level: intermediate
27720ce7577fSVaclav Hapla 
2773d4636a37SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart()
27740ce7577fSVaclav Hapla @*/
27750ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
27760ce7577fSVaclav Hapla {
27770ce7577fSVaclav Hapla   PetscSection        cs, newcs;
27780ce7577fSVaclav Hapla   PetscInt            *cones;
27790ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
27800ce7577fSVaclav Hapla   PetscInt            n;
27810ce7577fSVaclav Hapla 
27820ce7577fSVaclav Hapla   PetscFunctionBegin;
27839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
27849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
27859566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL));
27860ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
27870ce7577fSVaclav Hapla   if (pCones) {
27889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
27899566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
27900ce7577fSVaclav Hapla   }
27910ce7577fSVaclav Hapla   PetscFunctionReturn(0);
27920ce7577fSVaclav Hapla }
27930ce7577fSVaclav Hapla 
2794af9eab45SVaclav Hapla /*@
2795af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2796d4636a37SVaclav Hapla 
2797d4636a37SVaclav Hapla   Not collective
2798d4636a37SVaclav Hapla 
2799d4636a37SVaclav Hapla   Input Parameters:
2800d4636a37SVaclav Hapla + dm - The DMPlex
2801af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2802d4636a37SVaclav Hapla 
2803d4636a37SVaclav Hapla   Output Parameter:
2804af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2805d4636a37SVaclav Hapla 
2806d4636a37SVaclav Hapla   Level: advanced
2807d4636a37SVaclav Hapla 
2808af9eab45SVaclav Hapla   Notes:
2809af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2810af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2811af9eab45SVaclav Hapla 
2812af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth()
2813d4636a37SVaclav Hapla @*/
2814af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2815d4636a37SVaclav Hapla {
2816af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2817af9eab45SVaclav Hapla   PetscInt            depth;
2818d4636a37SVaclav Hapla 
2819d4636a37SVaclav Hapla   PetscFunctionBegin;
2820af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2821af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2822af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
28239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2824af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
28259566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
28269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2827af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2828af9eab45SVaclav Hapla }
2829af9eab45SVaclav Hapla 
2830af9eab45SVaclav Hapla /*@
2831af9eab45SVaclav 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).
2832af9eab45SVaclav Hapla 
2833af9eab45SVaclav Hapla   Not collective
2834af9eab45SVaclav Hapla 
2835af9eab45SVaclav Hapla   Input Parameters:
2836af9eab45SVaclav Hapla + dm - The DMPlex
2837af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2838af9eab45SVaclav Hapla 
2839d8d19677SJose E. Roman   Output Parameters:
2840af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2841af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2842af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2843af9eab45SVaclav Hapla 
2844af9eab45SVaclav Hapla   Level: advanced
2845af9eab45SVaclav Hapla 
2846af9eab45SVaclav Hapla   Notes:
2847af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2848af9eab45SVaclav Hapla 
2849af9eab45SVaclav 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.
2850af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2851af9eab45SVaclav Hapla 
2852af9eab45SVaclav Hapla   Array section has size equal to depth.  Each PetscSection sections[d] realizes mapping from expandedPoints[d+1] (section points) to expandedPoints[d] (section dofs) as follows:
2853af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2854af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2855af9eab45SVaclav Hapla 
2856af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2857af9eab45SVaclav Hapla @*/
2858af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2859af9eab45SVaclav Hapla {
2860af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2861af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2862af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2863af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2864af9eab45SVaclav Hapla   PetscSection        *sections_;
2865af9eab45SVaclav Hapla 
2866af9eab45SVaclav Hapla   PetscFunctionBegin;
2867af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2868af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2869af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2870af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2871af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
28729566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
28739566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
28749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
28759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
28769566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2877af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2878af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
28799566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
28809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2881af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
28829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end));
2883af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
28849566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
28859566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2886af9eab45SVaclav Hapla       } else {
28879566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2888af9eab45SVaclav Hapla       }
2889af9eab45SVaclav Hapla     }
28909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
28919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
28929566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2893af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
28949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
28959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2896af9eab45SVaclav Hapla       if (cn > 1) {
28979566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
28989566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt)));
2899af9eab45SVaclav Hapla       } else {
2900af9eab45SVaclav Hapla         newarr[co] = arr[i];
2901af9eab45SVaclav Hapla       }
2902af9eab45SVaclav Hapla     }
29039566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2904af9eab45SVaclav Hapla     arr = newarr;
2905af9eab45SVaclav Hapla     n = newn;
2906af9eab45SVaclav Hapla   }
29079566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
2908af9eab45SVaclav Hapla   *depth = depth_;
2909af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2910af9eab45SVaclav Hapla   else {
29119566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
29129566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
2913af9eab45SVaclav Hapla   }
2914af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2915af9eab45SVaclav Hapla   else {
29169566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
29179566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
2918af9eab45SVaclav Hapla   }
2919af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2920af9eab45SVaclav Hapla }
2921af9eab45SVaclav Hapla 
2922af9eab45SVaclav Hapla /*@
2923af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2924af9eab45SVaclav Hapla 
2925af9eab45SVaclav Hapla   Not collective
2926af9eab45SVaclav Hapla 
2927af9eab45SVaclav Hapla   Input Parameters:
2928af9eab45SVaclav Hapla + dm - The DMPlex
2929af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2930af9eab45SVaclav Hapla 
2931d8d19677SJose E. Roman   Output Parameters:
2932af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2933af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2934af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2935af9eab45SVaclav Hapla 
2936af9eab45SVaclav Hapla   Level: advanced
2937af9eab45SVaclav Hapla 
2938af9eab45SVaclav Hapla   Notes:
2939af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2940af9eab45SVaclav Hapla 
2941af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2942af9eab45SVaclav Hapla @*/
2943af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2944af9eab45SVaclav Hapla {
2945af9eab45SVaclav Hapla   PetscInt            d, depth_;
2946af9eab45SVaclav Hapla 
2947af9eab45SVaclav Hapla   PetscFunctionBegin;
29489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29492c71b3e2SJacob Faibussowitsch   PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2950af9eab45SVaclav Hapla   if (depth) *depth = 0;
2951af9eab45SVaclav Hapla   if (expandedPoints) {
29529566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
29539566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
2954af9eab45SVaclav Hapla   }
2955af9eab45SVaclav Hapla   if (sections)  {
29569566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
29579566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
2958af9eab45SVaclav Hapla   }
2959d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2960d4636a37SVaclav Hapla }
2961d4636a37SVaclav Hapla 
2962552f7358SJed Brown /*@
296392371b87SBarry 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
2964552f7358SJed Brown 
2965552f7358SJed Brown   Not collective
2966552f7358SJed Brown 
2967552f7358SJed Brown   Input Parameters:
2968552f7358SJed Brown + mesh - The DMPlex
2969eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2970552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
2971552f7358SJed Brown 
2972552f7358SJed Brown   Output Parameter:
2973552f7358SJed Brown 
2974552f7358SJed Brown   Note:
2975552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
2976552f7358SJed Brown 
2977552f7358SJed Brown   Level: beginner
2978552f7358SJed Brown 
297992371b87SBarry Smith .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize()
2980552f7358SJed Brown @*/
2981552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
2982552f7358SJed Brown {
2983552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2984552f7358SJed Brown   PetscInt       pStart, pEnd;
2985552f7358SJed Brown   PetscInt       dof, off, c;
2986552f7358SJed Brown 
2987552f7358SJed Brown   PetscFunctionBegin;
2988552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
29909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
2991dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
29929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
29932c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
2994552f7358SJed Brown   for (c = 0; c < dof; ++c) {
29952c71b3e2SJacob Faibussowitsch     PetscCheckFalse((cone[c] < pStart) || (cone[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd);
2996552f7358SJed Brown     mesh->cones[off+c] = cone[c];
2997552f7358SJed Brown   }
2998552f7358SJed Brown   PetscFunctionReturn(0);
2999552f7358SJed Brown }
3000552f7358SJed Brown 
3001552f7358SJed Brown /*@C
3002eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3003552f7358SJed Brown 
3004552f7358SJed Brown   Not collective
3005552f7358SJed Brown 
3006552f7358SJed Brown   Input Parameters:
3007552f7358SJed Brown + mesh - The DMPlex
3008eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3009552f7358SJed Brown 
3010552f7358SJed Brown   Output Parameter:
3011552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3012b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3013552f7358SJed Brown 
3014552f7358SJed Brown   Level: beginner
3015552f7358SJed Brown 
3016b5a892a1SMatthew G. Knepley   Notes:
3017b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3018b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3019b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
3020b5a892a1SMatthew G. Knepley   with the identity.
3021b5a892a1SMatthew G. Knepley 
30223813dfbdSMatthew G Knepley   Fortran Notes:
30233813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30243813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30253b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
3026922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
30273813dfbdSMatthew G Knepley 
3028b5a892a1SMatthew G. Knepley .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart()
3029552f7358SJed Brown @*/
3030552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3031552f7358SJed Brown {
3032552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3033552f7358SJed Brown   PetscInt       off;
3034552f7358SJed Brown 
3035552f7358SJed Brown   PetscFunctionBegin;
3036552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
303776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3038552f7358SJed Brown     PetscInt dof;
30399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3040552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3041552f7358SJed Brown   }
30429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30430d644c17SKarl Rupp 
3044552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3045552f7358SJed Brown   PetscFunctionReturn(0);
3046552f7358SJed Brown }
3047552f7358SJed Brown 
3048552f7358SJed Brown /*@
3049eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3050552f7358SJed Brown 
3051552f7358SJed Brown   Not collective
3052552f7358SJed Brown 
3053552f7358SJed Brown   Input Parameters:
3054552f7358SJed Brown + mesh - The DMPlex
3055eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3056b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3057552f7358SJed Brown   Output Parameter:
3058552f7358SJed Brown 
3059b5a892a1SMatthew G. Knepley   Notes:
3060552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3061552f7358SJed Brown 
3062b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3063b5a892a1SMatthew G. Knepley 
3064552f7358SJed Brown   Level: beginner
3065552f7358SJed Brown 
3066552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
3067552f7358SJed Brown @*/
3068552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3069552f7358SJed Brown {
3070552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3071552f7358SJed Brown   PetscInt       pStart, pEnd;
3072552f7358SJed Brown   PetscInt       dof, off, c;
3073552f7358SJed Brown 
3074552f7358SJed Brown   PetscFunctionBegin;
3075552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3078dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
30799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30802c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
3081552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3082552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3083552f7358SJed Brown 
30849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof));
30852c71b3e2SJacob Faibussowitsch     PetscCheckFalse(o && ((o < -(cdof+1)) || (o >= cdof)),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof);
3086552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
3087552f7358SJed Brown   }
3088552f7358SJed Brown   PetscFunctionReturn(0);
3089552f7358SJed Brown }
3090552f7358SJed Brown 
30917cd05799SMatthew G. Knepley /*@
3092eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
30937cd05799SMatthew G. Knepley 
30947cd05799SMatthew G. Knepley   Not collective
30957cd05799SMatthew G. Knepley 
30967cd05799SMatthew G. Knepley   Input Parameters:
30977cd05799SMatthew G. Knepley + mesh - The DMPlex
3098eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
30997cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31007cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31017cd05799SMatthew G. Knepley 
31027cd05799SMatthew G. Knepley   Level: beginner
31037cd05799SMatthew G. Knepley 
31047cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
31057cd05799SMatthew G. Knepley @*/
3106552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3107552f7358SJed Brown {
3108552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3109552f7358SJed Brown   PetscInt       pStart, pEnd;
3110552f7358SJed Brown   PetscInt       dof, off;
3111552f7358SJed Brown 
3112552f7358SJed Brown   PetscFunctionBegin;
3113552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31152c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
31162c71b3e2SJacob Faibussowitsch   PetscCheckFalse((conePoint < pStart) || (conePoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd);
31179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
31192c71b3e2SJacob Faibussowitsch   PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
3120552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
3121552f7358SJed Brown   PetscFunctionReturn(0);
3122552f7358SJed Brown }
3123552f7358SJed Brown 
31247cd05799SMatthew G. Knepley /*@
3125eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
31267cd05799SMatthew G. Knepley 
31277cd05799SMatthew G. Knepley   Not collective
31287cd05799SMatthew G. Knepley 
31297cd05799SMatthew G. Knepley   Input Parameters:
31307cd05799SMatthew G. Knepley + mesh - The DMPlex
3131eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31327cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31337cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
31347cd05799SMatthew G. Knepley 
31357cd05799SMatthew G. Knepley   Level: beginner
31367cd05799SMatthew G. Knepley 
3137b5a892a1SMatthew G. Knepley   Notes:
3138b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3139b5a892a1SMatthew G. Knepley 
31407cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
31417cd05799SMatthew G. Knepley @*/
314277c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
314377c88f5bSMatthew G Knepley {
314477c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
314577c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
314677c88f5bSMatthew G Knepley   PetscInt       dof, off;
314777c88f5bSMatthew G Knepley 
314877c88f5bSMatthew G Knepley   PetscFunctionBegin;
314977c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31512c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
31529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
31542c71b3e2SJacob Faibussowitsch   PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
315577c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
315677c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
315777c88f5bSMatthew G Knepley }
315877c88f5bSMatthew G Knepley 
3159552f7358SJed Brown /*@
3160eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3161552f7358SJed Brown 
3162552f7358SJed Brown   Not collective
3163552f7358SJed Brown 
3164552f7358SJed Brown   Input Parameters:
3165552f7358SJed Brown + mesh - The DMPlex
3166eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3167552f7358SJed Brown 
3168552f7358SJed Brown   Output Parameter:
3169552f7358SJed Brown . size - The support size for point p
3170552f7358SJed Brown 
3171552f7358SJed Brown   Level: beginner
3172552f7358SJed Brown 
3173552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize()
3174552f7358SJed Brown @*/
3175552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3176552f7358SJed Brown {
3177552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3178552f7358SJed Brown 
3179552f7358SJed Brown   PetscFunctionBegin;
3180552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3181dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
31829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
3183552f7358SJed Brown   PetscFunctionReturn(0);
3184552f7358SJed Brown }
3185552f7358SJed Brown 
3186552f7358SJed Brown /*@
3187eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3188552f7358SJed Brown 
3189552f7358SJed Brown   Not collective
3190552f7358SJed Brown 
3191552f7358SJed Brown   Input Parameters:
3192552f7358SJed Brown + mesh - The DMPlex
3193eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3194552f7358SJed Brown - size - The support size for point p
3195552f7358SJed Brown 
3196552f7358SJed Brown   Output Parameter:
3197552f7358SJed Brown 
3198552f7358SJed Brown   Note:
3199552f7358SJed Brown   This should be called after DMPlexSetChart().
3200552f7358SJed Brown 
3201552f7358SJed Brown   Level: beginner
3202552f7358SJed Brown 
3203552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart()
3204552f7358SJed Brown @*/
3205552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3206552f7358SJed Brown {
3207552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3208552f7358SJed Brown 
3209552f7358SJed Brown   PetscFunctionBegin;
3210552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
3212552f7358SJed Brown   PetscFunctionReturn(0);
3213552f7358SJed Brown }
3214552f7358SJed Brown 
3215552f7358SJed Brown /*@C
3216eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3217552f7358SJed Brown 
3218552f7358SJed Brown   Not collective
3219552f7358SJed Brown 
3220552f7358SJed Brown   Input Parameters:
3221552f7358SJed Brown + mesh - The DMPlex
3222eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3223552f7358SJed Brown 
3224552f7358SJed Brown   Output Parameter:
3225552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3226552f7358SJed Brown 
3227552f7358SJed Brown   Level: beginner
3228552f7358SJed Brown 
32293813dfbdSMatthew G Knepley   Fortran Notes:
32303813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32313813dfbdSMatthew G Knepley   include petsc.h90 in your code.
32323b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3233922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
32343813dfbdSMatthew G Knepley 
3235e45f02b0SMatthew G. Knepley .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart()
3236552f7358SJed Brown @*/
3237552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3238552f7358SJed Brown {
3239552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3240552f7358SJed Brown   PetscInt       off;
3241552f7358SJed Brown 
3242552f7358SJed Brown   PetscFunctionBegin;
3243552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3244552f7358SJed Brown   PetscValidPointer(support, 3);
32459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3246552f7358SJed Brown   *support = &mesh->supports[off];
3247552f7358SJed Brown   PetscFunctionReturn(0);
3248552f7358SJed Brown }
3249552f7358SJed Brown 
3250552f7358SJed Brown /*@
325192371b87SBarry 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
3252552f7358SJed Brown 
3253552f7358SJed Brown   Not collective
3254552f7358SJed Brown 
3255552f7358SJed Brown   Input Parameters:
3256552f7358SJed Brown + mesh - The DMPlex
3257eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
325892371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3259552f7358SJed Brown 
3260552f7358SJed Brown   Output Parameter:
3261552f7358SJed Brown 
3262552f7358SJed Brown   Note:
3263552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3264552f7358SJed Brown 
3265552f7358SJed Brown   Level: beginner
3266552f7358SJed Brown 
326792371b87SBarry Smith .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp()
3268552f7358SJed Brown @*/
3269552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3270552f7358SJed Brown {
3271552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3272552f7358SJed Brown   PetscInt       pStart, pEnd;
3273552f7358SJed Brown   PetscInt       dof, off, c;
3274552f7358SJed Brown 
3275552f7358SJed Brown   PetscFunctionBegin;
3276552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
32789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3279dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
32809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
32812c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
3282552f7358SJed Brown   for (c = 0; c < dof; ++c) {
32832c71b3e2SJacob Faibussowitsch     PetscCheckFalse((support[c] < pStart) || (support[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd);
3284552f7358SJed Brown     mesh->supports[off+c] = support[c];
3285552f7358SJed Brown   }
3286552f7358SJed Brown   PetscFunctionReturn(0);
3287552f7358SJed Brown }
3288552f7358SJed Brown 
32897cd05799SMatthew G. Knepley /*@
3290eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
32917cd05799SMatthew G. Knepley 
32927cd05799SMatthew G. Knepley   Not collective
32937cd05799SMatthew G. Knepley 
32947cd05799SMatthew G. Knepley   Input Parameters:
32957cd05799SMatthew G. Knepley + mesh - The DMPlex
3296eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
32977cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
32987cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
32997cd05799SMatthew G. Knepley 
33007cd05799SMatthew G. Knepley   Level: beginner
33017cd05799SMatthew G. Knepley 
33027cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
33037cd05799SMatthew G. Knepley @*/
3304552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3305552f7358SJed Brown {
3306552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3307552f7358SJed Brown   PetscInt       pStart, pEnd;
3308552f7358SJed Brown   PetscInt       dof, off;
3309552f7358SJed Brown 
3310552f7358SJed Brown   PetscFunctionBegin;
3311552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
33149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
33152c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
33162c71b3e2SJacob Faibussowitsch   PetscCheckFalse((supportPoint < pStart) || (supportPoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd);
33172c71b3e2SJacob Faibussowitsch   PetscCheckFalse(supportPos >= dof,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof);
3318552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3319552f7358SJed Brown   PetscFunctionReturn(0);
3320552f7358SJed Brown }
3321552f7358SJed Brown 
3322b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3323b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3324b5a892a1SMatthew G. Knepley {
3325b5a892a1SMatthew G. Knepley   switch (ct) {
3326b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3327b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3328b5a892a1SMatthew G. Knepley       break;
3329b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3330b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3331b5a892a1SMatthew G. Knepley       if (o == -2) return -3;
3332b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3333b5a892a1SMatthew G. Knepley       break;
3334b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3335b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3336b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3337b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3338b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3339b5a892a1SMatthew G. Knepley       break;
3340b5a892a1SMatthew G. Knepley     default: return o;
3341b5a892a1SMatthew G. Knepley   }
3342b5a892a1SMatthew G. Knepley   return o;
3343b5a892a1SMatthew G. Knepley }
3344b5a892a1SMatthew G. Knepley 
3345b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3346b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3347b5a892a1SMatthew G. Knepley {
3348b5a892a1SMatthew G. Knepley   switch (ct) {
3349b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3350b5a892a1SMatthew G. Knepley       if ((o == -2) || (o == 1)) return -1;
3351b5a892a1SMatthew G. Knepley       if (o == -1) return 0;
3352b5a892a1SMatthew G. Knepley       break;
3353b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3354b5a892a1SMatthew G. Knepley       if (o == -3) return -2;
3355b5a892a1SMatthew G. Knepley       if (o == -2) return -1;
3356b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3357b5a892a1SMatthew G. Knepley       break;
3358b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3359b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3360b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3361b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3362b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3363b5a892a1SMatthew G. Knepley       break;
3364b5a892a1SMatthew G. Knepley     default: return o;
3365b5a892a1SMatthew G. Knepley   }
3366b5a892a1SMatthew G. Knepley   return o;
3367b5a892a1SMatthew G. Knepley }
3368b5a892a1SMatthew G. Knepley 
3369b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3370b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3371b5a892a1SMatthew G. Knepley {
3372b5a892a1SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3373b5a892a1SMatthew G. Knepley 
3374b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
33759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3376b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3377b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3378b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3379b5a892a1SMatthew G. Knepley 
33809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
33819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
33829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3383b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3384b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3385b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3386b5a892a1SMatthew G. Knepley 
33879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3388b5a892a1SMatthew G. Knepley       switch (ct) {
3389b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
33909566063dSJacob Faibussowitsch           if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
33919566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3392b5a892a1SMatthew G. Knepley           break;
3393b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
33949566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
33959566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
33969566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3397b5a892a1SMatthew G. Knepley           break;
3398b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
33999566063dSJacob Faibussowitsch           if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34009566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34019566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
34029566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3403b5a892a1SMatthew G. Knepley           break;
3404b5a892a1SMatthew G. Knepley         default: break;
3405b5a892a1SMatthew G. Knepley       }
3406b5a892a1SMatthew G. Knepley     }
3407b5a892a1SMatthew G. Knepley   }
3408b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3409b5a892a1SMatthew G. Knepley }
3410b5a892a1SMatthew G. Knepley 
3411012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3412b5a892a1SMatthew G. Knepley {
3413b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3414b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3415b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3416b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3417b5a892a1SMatthew G. Knepley 
3418b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3419b5a892a1SMatthew G. Knepley   if (ornt) {
34209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3421b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3422b5a892a1SMatthew G. Knepley   }
3423b5a892a1SMatthew G. Knepley   if (*points) {
3424b5a892a1SMatthew G. Knepley     closure = *points;
3425b5a892a1SMatthew G. Knepley   } else {
3426b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
34279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
34289566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure));
3429b5a892a1SMatthew G. Knepley   }
3430b5a892a1SMatthew G. Knepley   if (useCone) {
34319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
34329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
34339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3434b5a892a1SMatthew G. Knepley   } else {
34359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
34369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3437b5a892a1SMatthew G. Knepley   }
3438b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3439b5a892a1SMatthew G. Knepley     closure[off++] = p;
3440b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3441b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3442b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3443b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3444b5a892a1SMatthew G. Knepley     }
3445b5a892a1SMatthew G. Knepley   } else {
34465f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3447b5a892a1SMatthew G. Knepley 
3448b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3449b5a892a1SMatthew G. Knepley     closure[off++] = p;
3450b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3451b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3452b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3453b5a892a1SMatthew G. Knepley 
34549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3455b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3456b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3457b5a892a1SMatthew G. Knepley     }
3458b5a892a1SMatthew G. Knepley   }
3459b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize+1;
3460b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3461b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3462b5a892a1SMatthew G. Knepley }
3463b5a892a1SMatthew G. Knepley 
3464b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
3465b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3466b5a892a1SMatthew G. Knepley {
3467b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3468b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3469b5a892a1SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
3470b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3471b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3472b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3473b5a892a1SMatthew G. Knepley 
3474b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
34759566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
34769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
34779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
34789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
34799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3480b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    dim+1)-1)/(maxConeSize-1))    : dim+1;
3481b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1;
3482b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3483b5a892a1SMatthew G. Knepley   if (*points) {pts  = *points;}
34849566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts));
3485b5a892a1SMatthew G. Knepley   c    = 0;
3486b5a892a1SMatthew G. Knepley   pts[c++] = point;
3487b5a892a1SMatthew G. Knepley   pts[c++] = o;
34889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft));
34899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure));
3490b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
34919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure));
3492b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
34939566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3494b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
34959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft));
3496b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d*2+0]];
3497b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]);
3498b5a892a1SMatthew G. Knepley   }
3499b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3500b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3501b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d*2+0]];
3502b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3503b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3504b5a892a1SMatthew G. Knepley 
35059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3506b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]));
35079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
35089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
35099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3510b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3511b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc*2+0]];
3512b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc*2+1];
3513b5a892a1SMatthew G. Knepley 
3514b5a892a1SMatthew G. Knepley         for (i = 0; i < c; i += 2) if (pts[i] == cp) break;
3515b5a892a1SMatthew G. Knepley         if (i == c) {
35169566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3517b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3518b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]);
3519b5a892a1SMatthew G. Knepley         }
3520b5a892a1SMatthew G. Knepley       }
3521b5a892a1SMatthew G. Knepley     }
3522b5a892a1SMatthew G. Knepley   }
3523b5a892a1SMatthew G. Knepley   *numPoints = c/2;
3524b5a892a1SMatthew G. Knepley   *points    = pts;
3525b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3526b5a892a1SMatthew G. Knepley }
3527b5a892a1SMatthew G. Knepley 
3528b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3529b5a892a1SMatthew G. Knepley {
3530b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3531b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3532b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3533b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3534b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3535b5a892a1SMatthew G. Knepley 
3536b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3538b5a892a1SMatthew G. Knepley   if (depth == 1) {
35399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3540b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3541b5a892a1SMatthew G. Knepley   }
35429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3543b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3544b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
35459566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3546b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3547b5a892a1SMatthew G. Knepley   }
35489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3549b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    depth+1)-1)/(maxConeSize-1))    : depth+1;
3550b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1;
3551b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
35529566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3553b5a892a1SMatthew G. Knepley   if (*points) {closure = *points;}
35549566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure));
3555b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3556b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3557b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3558b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3559b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3560b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3561b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3562b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3563b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3564b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType) fifo[fifoStart++];
3565b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3566b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3567b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3568b5a892a1SMatthew G. Knepley 
3569b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3570b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2;
35712c71b3e2SJacob Faibussowitsch       PetscCheckFalse(o && (o >= nO || o < -nO),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %D not in [%D,%D) for %s %D", o, -nO, nO, DMPolytopeTypes[qt], q);
3572b5a892a1SMatthew G. Knepley     }
3573b5a892a1SMatthew G. Knepley     if (useCone) {
35749566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
35759566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
35769566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3577b5a892a1SMatthew G. Knepley     } else {
35789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
35799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3580b5a892a1SMatthew G. Knepley       tmpO = NULL;
3581b5a892a1SMatthew G. Knepley     }
3582b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3583b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t*2]   : t;
3584b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0;
3585b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
35869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3587b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3588b5a892a1SMatthew G. Knepley       PetscInt       c;
3589b5a892a1SMatthew G. Knepley 
3590b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3591b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3592b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3593b5a892a1SMatthew G. Knepley       }
3594b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3595b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3596b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3597b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3598b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3599b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3600b5a892a1SMatthew G. Knepley       }
3601b5a892a1SMatthew G. Knepley     }
3602b5a892a1SMatthew G. Knepley   }
36039566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3604b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
3605b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3606b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3607b5a892a1SMatthew G. Knepley }
3608b5a892a1SMatthew G. Knepley 
3609552f7358SJed Brown /*@C
3610eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3611552f7358SJed Brown 
3612552f7358SJed Brown   Not collective
3613552f7358SJed Brown 
3614552f7358SJed Brown   Input Parameters:
3615b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3616b5a892a1SMatthew G. Knepley . p       - The mesh point
36176b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3618552f7358SJed Brown 
36196b867d5aSJose E. Roman   Input/Output Parameter:
36206b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
36216b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
36226b867d5aSJose E. Roman 
36236b867d5aSJose E. Roman   Output Parameter:
36246b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3625552f7358SJed Brown 
3626552f7358SJed Brown   Note:
36270298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3628552f7358SJed Brown 
36293813dfbdSMatthew G Knepley   Fortran Notes:
3630b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36313813dfbdSMatthew G Knepley 
36323813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36333813dfbdSMatthew G Knepley 
3634552f7358SJed Brown   Level: beginner
3635552f7358SJed Brown 
3636552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3637552f7358SJed Brown @*/
3638552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3639552f7358SJed Brown {
3640b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3641552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3642b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3643b5a892a1SMatthew G. Knepley   if (points)    PetscValidPointer(points, 5);
36449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
36459bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36469bf0dad6SMatthew G. Knepley }
36479bf0dad6SMatthew G. Knepley 
3648552f7358SJed Brown /*@C
3649eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3650552f7358SJed Brown 
3651552f7358SJed Brown   Not collective
3652552f7358SJed Brown 
3653552f7358SJed Brown   Input Parameters:
3654b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3655b5a892a1SMatthew G. Knepley . p         - The mesh point
3656b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3657b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3658b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3659552f7358SJed Brown 
3660552f7358SJed Brown   Note:
36610298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3662552f7358SJed Brown 
36633813dfbdSMatthew G Knepley   Fortran Notes:
3664b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36653813dfbdSMatthew G Knepley 
36663813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36673813dfbdSMatthew G Knepley 
3668552f7358SJed Brown   Level: beginner
3669552f7358SJed Brown 
3670552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3671552f7358SJed Brown @*/
3672552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3673552f7358SJed Brown {
3674b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3675552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36764ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
36779566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3678552f7358SJed Brown   PetscFunctionReturn(0);
3679552f7358SJed Brown }
3680552f7358SJed Brown 
3681552f7358SJed Brown /*@
3682eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3683552f7358SJed Brown 
3684552f7358SJed Brown   Not collective
3685552f7358SJed Brown 
3686552f7358SJed Brown   Input Parameter:
3687552f7358SJed Brown . mesh - The DMPlex
3688552f7358SJed Brown 
3689552f7358SJed Brown   Output Parameters:
3690552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3691552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3692552f7358SJed Brown 
3693552f7358SJed Brown   Level: beginner
3694552f7358SJed Brown 
3695552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
3696552f7358SJed Brown @*/
3697552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3698552f7358SJed Brown {
3699552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3700552f7358SJed Brown 
3701552f7358SJed Brown   PetscFunctionBegin;
3702552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3703*6302a7fbSVaclav Hapla   if (maxConeSize) {
3704*6302a7fbSVaclav Hapla     PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
3705*6302a7fbSVaclav Hapla   }
3706*6302a7fbSVaclav Hapla   if (maxSupportSize) {
3707*6302a7fbSVaclav Hapla     PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
3708*6302a7fbSVaclav Hapla   }
3709552f7358SJed Brown   PetscFunctionReturn(0);
3710552f7358SJed Brown }
3711552f7358SJed Brown 
3712552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3713552f7358SJed Brown {
3714552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3715*6302a7fbSVaclav Hapla   PetscInt       size, maxSupportSize;
3716552f7358SJed Brown 
3717552f7358SJed Brown   PetscFunctionBegin;
3718552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37199566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
37209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
37219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
37229566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
37239566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt)));
3724*6302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
3725*6302a7fbSVaclav Hapla   if (maxSupportSize) {
37269566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
37279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
37289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
37299566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt)));
3730552f7358SJed Brown   }
3731552f7358SJed Brown   PetscFunctionReturn(0);
3732552f7358SJed Brown }
3733552f7358SJed Brown 
3734276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3735552f7358SJed Brown {
3736552f7358SJed Brown   PetscFunctionBegin;
37379566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
37389566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3739c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3740736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3741f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3742f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3743f94b4a02SBlaise Bourdin 
37443dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) dm->sfMigration));
37469566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection((*subdm), &section));
37479566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv));
37489566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq));
37499566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
3750f94b4a02SBlaise Bourdin 
37519566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural));
3752c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
37539566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&sectionSeq));
37549566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfMigrationInv));
3755f94b4a02SBlaise Bourdin   }
3756552f7358SJed Brown   PetscFunctionReturn(0);
3757552f7358SJed Brown }
3758552f7358SJed Brown 
37592adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
37602adcc780SMatthew G. Knepley {
37613dcd263cSBlaise Bourdin   PetscInt       i = 0;
37622adcc780SMatthew G. Knepley 
37632adcc780SMatthew G. Knepley   PetscFunctionBegin;
37649566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
37659566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3766c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
37673dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
37683dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
37693dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
37703dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
37713dcd263cSBlaise Bourdin 
37723dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
37739566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration));
3774c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
37759566063dSJacob Faibussowitsch       PetscCall(DMGetLocalSection((*superdm), &section));
37769566063dSJacob Faibussowitsch       PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv));
37779566063dSJacob Faibussowitsch       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq));
37789566063dSJacob Faibussowitsch       PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
37793dcd263cSBlaise Bourdin 
37809566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural));
3781c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
37829566063dSJacob Faibussowitsch       PetscCall(PetscSectionDestroy(&sectionSeq));
37839566063dSJacob Faibussowitsch       PetscCall(PetscSFDestroy(&sfMigrationInv));
37843dcd263cSBlaise Bourdin       break;
37853dcd263cSBlaise Bourdin     }
37863dcd263cSBlaise Bourdin   }
37872adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
37882adcc780SMatthew G. Knepley }
37892adcc780SMatthew G. Knepley 
3790552f7358SJed Brown /*@
3791eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3792552f7358SJed Brown 
3793552f7358SJed Brown   Not collective
3794552f7358SJed Brown 
3795552f7358SJed Brown   Input Parameter:
3796552f7358SJed Brown . mesh - The DMPlex
3797552f7358SJed Brown 
3798552f7358SJed Brown   Output Parameter:
3799552f7358SJed Brown 
3800552f7358SJed Brown   Note:
3801552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3802552f7358SJed Brown 
3803552f7358SJed Brown   Level: beginner
3804552f7358SJed Brown 
3805552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone()
3806552f7358SJed Brown @*/
3807552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3808552f7358SJed Brown {
3809552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3810552f7358SJed Brown   PetscInt      *offsets;
3811552f7358SJed Brown   PetscInt       supportSize;
3812552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3813552f7358SJed Brown 
3814552f7358SJed Brown   PetscFunctionBegin;
3815552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
381628b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
38179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0));
3818552f7358SJed Brown   /* Calculate support sizes */
38199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3820552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3821552f7358SJed Brown     PetscInt dof, off, c;
3822552f7358SJed Brown 
38239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3825552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
38269566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3827552f7358SJed Brown     }
3828552f7358SJed Brown   }
38299566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3830552f7358SJed Brown   /* Calculate supports */
38319566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
38329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
38339566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3834552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3835552f7358SJed Brown     PetscInt dof, off, c;
3836552f7358SJed Brown 
38379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38389566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3839552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3840552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3841552f7358SJed Brown       PetscInt       offS;
3842552f7358SJed Brown 
38439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
38440d644c17SKarl Rupp 
3845552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3846552f7358SJed Brown       ++offsets[q];
3847552f7358SJed Brown     }
3848552f7358SJed Brown   }
38499566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
38509566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0));
3851552f7358SJed Brown   PetscFunctionReturn(0);
3852552f7358SJed Brown }
3853552f7358SJed Brown 
3854277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3855277ea44aSLisandro Dalcin {
3856277ea44aSLisandro Dalcin   IS             stratumIS;
3857277ea44aSLisandro Dalcin 
3858277ea44aSLisandro Dalcin   PetscFunctionBegin;
3859277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
386076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3861277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3862277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
38639566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
3864277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
38659566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3866277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3867277ea44aSLisandro Dalcin     }
386828b400f6SJacob Faibussowitsch     PetscCheck(!overlap,PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %D range [%D,%D) overlaps with depth %D range [%D,%D)", depth, pStart, pEnd, level, qStart, qEnd);
3869277ea44aSLisandro Dalcin   }
38709566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS));
38719566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
38729566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
3873277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3874277ea44aSLisandro Dalcin }
3875277ea44aSLisandro Dalcin 
3876552f7358SJed Brown /*@
3877a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
38786dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3879552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3880552f7358SJed Brown   the DAG.
3881552f7358SJed Brown 
3882bf4602e4SToby Isaac   Collective on dm
3883552f7358SJed Brown 
3884552f7358SJed Brown   Input Parameter:
3885552f7358SJed Brown . mesh - The DMPlex
3886552f7358SJed Brown 
3887552f7358SJed Brown   Output Parameter:
3888552f7358SJed Brown 
3889552f7358SJed Brown   Notes:
3890b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3891b1bb481bSMatthew 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
3892b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3893c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3894150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3895552f7358SJed Brown 
3896b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3897b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3898b1bb481bSMatthew 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
3899b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3900b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3901b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3902b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3903b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3904b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3905b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3906b1bb481bSMatthew Knepley 
3907150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3908552f7358SJed Brown 
3909552f7358SJed Brown   Level: beginner
3910552f7358SJed Brown 
3911ba2698f1SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes()
3912552f7358SJed Brown @*/
3913552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3914552f7358SJed Brown {
3915df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3916aa50250dSMatthew G. Knepley   DMLabel        label;
3917552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3918552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3919552f7358SJed Brown 
3920552f7358SJed Brown   PetscFunctionBegin;
3921552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0));
3923277ea44aSLisandro Dalcin 
3924277ea44aSLisandro Dalcin   /* Create depth label */
39259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
39269566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
39279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
3928277ea44aSLisandro Dalcin 
3929277ea44aSLisandro Dalcin   {
3930552f7358SJed Brown     /* Initialize roots and count leaves */
3931277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3932277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3933552f7358SJed Brown     PetscInt coneSize, supportSize;
3934552f7358SJed Brown 
3935277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3938552f7358SJed Brown       if (!coneSize && supportSize) {
3939277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3940277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3941552f7358SJed Brown         ++numRoots;
3942552f7358SJed Brown       } else if (!supportSize && coneSize) {
3943552f7358SJed Brown         ++numLeaves;
3944552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3945552f7358SJed Brown         /* Isolated points */
3946277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3947277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3948552f7358SJed Brown       }
3949552f7358SJed Brown     }
39509566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1));
3951277ea44aSLisandro Dalcin   }
3952277ea44aSLisandro Dalcin 
3953552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3954277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3955277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3956552f7358SJed Brown     PetscInt coneSize, supportSize;
3957552f7358SJed Brown 
3958277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3961552f7358SJed Brown       if (!supportSize && coneSize) {
3962277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3963277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3964552f7358SJed Brown       }
3965552f7358SJed Brown     }
39669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1));
3967552f7358SJed Brown   } else {
3968277ea44aSLisandro Dalcin     PetscInt level = 0;
3969277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3970552f7358SJed Brown 
39719566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3972277ea44aSLisandro Dalcin     while (qEnd > qStart) {
3973277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
3974277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
397574ef644bSMatthew G. Knepley 
3976277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
397774ef644bSMatthew G. Knepley         const PetscInt *support;
397874ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
397974ef644bSMatthew G. Knepley 
39809566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
39819566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
398274ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
3983277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
3984277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
3985552f7358SJed Brown         }
3986552f7358SJed Brown       }
39879566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
39889566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1));
39899566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
399074ef644bSMatthew G. Knepley     }
399174ef644bSMatthew G. Knepley   }
3992bf4602e4SToby Isaac   { /* just in case there is an empty process */
3993bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
3994bf4602e4SToby Isaac 
39959566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
39969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm)));
3997bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
39989566063dSJacob Faibussowitsch       PetscCall(DMLabelAddStratum(label, v));
3999bf4602e4SToby Isaac     }
4000bf4602e4SToby Isaac   }
40019566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState));
40029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0));
4003552f7358SJed Brown   PetscFunctionReturn(0);
4004552f7358SJed Brown }
4005552f7358SJed Brown 
4006412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4007ba2698f1SMatthew G. Knepley {
4008412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4009412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4010ba2698f1SMatthew G. Knepley 
4011412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
40129566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
40139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
40149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4015ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4016ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4017ba2698f1SMatthew G. Knepley     switch (pdepth) {
4018ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
4019ba2698f1SMatthew G. Knepley       case 1:
4020ba2698f1SMatthew G. Knepley         switch (coneSize) {
4021ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
4022ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4023ba2698f1SMatthew G. Knepley           case 4:
4024ba2698f1SMatthew G. Knepley           switch (dim) {
4025ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
4026ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
4027ba2698f1SMatthew G. Knepley             default: break;
4028ba2698f1SMatthew G. Knepley           }
4029ba2698f1SMatthew G. Knepley           break;
4030da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
4031ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4032ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
4033ba2698f1SMatthew G. Knepley         default: break;
4034ba2698f1SMatthew G. Knepley       }
4035ba2698f1SMatthew G. Knepley     }
4036ba2698f1SMatthew G. Knepley   } else {
4037ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4038ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4039ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4040ba2698f1SMatthew G. Knepley       switch (dim) {
4041ba2698f1SMatthew G. Knepley         case 1:
4042ba2698f1SMatthew G. Knepley           switch (coneSize) {
4043ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
4044ba2698f1SMatthew G. Knepley             default: break;
4045ba2698f1SMatthew G. Knepley           }
4046ba2698f1SMatthew G. Knepley           break;
4047ba2698f1SMatthew G. Knepley         case 2:
4048ba2698f1SMatthew G. Knepley           switch (coneSize) {
4049ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4050ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4051ba2698f1SMatthew G. Knepley             default: break;
4052ba2698f1SMatthew G. Knepley           }
4053ba2698f1SMatthew G. Knepley           break;
4054ba2698f1SMatthew G. Knepley         case 3:
4055ba2698f1SMatthew G. Knepley           switch (coneSize) {
4056ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
4057da9060c4SMatthew G. Knepley             case 5:
4058da9060c4SMatthew G. Knepley             {
4059da9060c4SMatthew G. Knepley               const PetscInt *cone;
4060da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
4061da9060c4SMatthew G. Knepley 
40629566063dSJacob Faibussowitsch               PetscCall(DMPlexGetCone(dm, p, &cone));
40639566063dSJacob Faibussowitsch               PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4064da9060c4SMatthew G. Knepley               switch (faceConeSize) {
4065da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4066da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
4067da9060c4SMatthew G. Knepley               }
4068da9060c4SMatthew G. Knepley             }
4069da9060c4SMatthew G. Knepley             break;
4070ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
4071ba2698f1SMatthew G. Knepley             default: break;
4072ba2698f1SMatthew G. Knepley           }
4073ba2698f1SMatthew G. Knepley           break;
4074ba2698f1SMatthew G. Knepley         default: break;
4075ba2698f1SMatthew G. Knepley       }
4076ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4077ba2698f1SMatthew G. Knepley       switch (coneSize) {
4078ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
4079ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4080ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4081ba2698f1SMatthew G. Knepley         default: break;
4082ba2698f1SMatthew G. Knepley       }
4083ba2698f1SMatthew G. Knepley     }
4084ba2698f1SMatthew G. Knepley   }
4085412e9a14SMatthew G. Knepley   *pt = ct;
4086412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4087ba2698f1SMatthew G. Knepley }
4088412e9a14SMatthew G. Knepley 
4089412e9a14SMatthew G. Knepley /*@
4090412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4091412e9a14SMatthew G. Knepley 
4092412e9a14SMatthew G. Knepley   Collective on dm
4093412e9a14SMatthew G. Knepley 
4094412e9a14SMatthew G. Knepley   Input Parameter:
4095412e9a14SMatthew G. Knepley . mesh - The DMPlex
4096412e9a14SMatthew G. Knepley 
4097412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4098412e9a14SMatthew G. Knepley 
4099412e9a14SMatthew G. Knepley   Level: developer
4100412e9a14SMatthew G. Knepley 
4101412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4102412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4103412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4104412e9a14SMatthew G. Knepley 
4105412e9a14SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel()
4106412e9a14SMatthew G. Knepley @*/
4107412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
4108412e9a14SMatthew G. Knepley {
4109412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
4110412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
4111412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
4112412e9a14SMatthew G. Knepley 
4113412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4114412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4115412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
41169566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
41179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
41189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4119412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4120327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4121412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4122412e9a14SMatthew G. Knepley 
41239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
41249566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
41252c71b3e2SJacob Faibussowitsch     PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p);
41269566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4127412e9a14SMatthew G. Knepley   }
41289566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState));
41299566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view"));
4130ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4131ba2698f1SMatthew G. Knepley }
4132ba2698f1SMatthew G. Knepley 
4133552f7358SJed Brown /*@C
4134552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4135552f7358SJed Brown 
4136552f7358SJed Brown   Not Collective
4137552f7358SJed Brown 
4138552f7358SJed Brown   Input Parameters:
4139552f7358SJed Brown + dm - The DMPlex object
4140552f7358SJed Brown . numPoints - The number of input points for the join
4141552f7358SJed Brown - points - The input points
4142552f7358SJed Brown 
4143552f7358SJed Brown   Output Parameters:
4144552f7358SJed Brown + numCoveredPoints - The number of points in the join
4145552f7358SJed Brown - coveredPoints - The points in the join
4146552f7358SJed Brown 
4147552f7358SJed Brown   Level: intermediate
4148552f7358SJed Brown 
4149552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4150552f7358SJed Brown 
41513813dfbdSMatthew G Knepley   Fortran Notes:
41523813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41533813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41543813dfbdSMatthew G Knepley 
41553813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41563813dfbdSMatthew G Knepley 
4157552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet()
4158552f7358SJed Brown @*/
4159552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4160552f7358SJed Brown {
4161552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4162552f7358SJed Brown   PetscInt      *join[2];
4163552f7358SJed Brown   PetscInt       joinSize, i = 0;
4164552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4165*6302a7fbSVaclav Hapla   PetscInt       maxSupportSize;
4166552f7358SJed Brown 
4167552f7358SJed Brown   PetscFunctionBegin;
4168552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
416948bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
417048bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
417148bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4172*6302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
4173*6302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
4174*6302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4175552f7358SJed Brown   /* Copy in support of first point */
41769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
41779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4178552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
4179552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
4180552f7358SJed Brown   }
4181552f7358SJed Brown   /* Check each successive support */
4182552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4183552f7358SJed Brown     PetscInt newJoinSize = 0;
4184552f7358SJed Brown 
41859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
41869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4187552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4188552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
4189552f7358SJed Brown 
4190552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4191552f7358SJed Brown         if (point == join[i][m]) {
4192552f7358SJed Brown           join[1-i][newJoinSize++] = point;
4193552f7358SJed Brown           break;
4194552f7358SJed Brown         }
4195552f7358SJed Brown       }
4196552f7358SJed Brown     }
4197552f7358SJed Brown     joinSize = newJoinSize;
4198552f7358SJed Brown     i        = 1-i;
4199552f7358SJed Brown   }
4200552f7358SJed Brown   *numCoveredPoints = joinSize;
4201552f7358SJed Brown   *coveredPoints    = join[i];
4202*6302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i]));
4203552f7358SJed Brown   PetscFunctionReturn(0);
4204552f7358SJed Brown }
4205552f7358SJed Brown 
4206552f7358SJed Brown /*@C
4207552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4208552f7358SJed Brown 
4209552f7358SJed Brown   Not Collective
4210552f7358SJed Brown 
4211552f7358SJed Brown   Input Parameters:
4212552f7358SJed Brown + dm - The DMPlex object
4213552f7358SJed Brown . numPoints - The number of input points for the join
4214552f7358SJed Brown - points - The input points
4215552f7358SJed Brown 
4216552f7358SJed Brown   Output Parameters:
4217552f7358SJed Brown + numCoveredPoints - The number of points in the join
4218552f7358SJed Brown - coveredPoints - The points in the join
4219552f7358SJed Brown 
42203813dfbdSMatthew G Knepley   Fortran Notes:
42213813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42223813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42233813dfbdSMatthew G Knepley 
42243813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42253813dfbdSMatthew G Knepley 
4226552f7358SJed Brown   Level: intermediate
4227552f7358SJed Brown 
4228552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet()
4229552f7358SJed Brown @*/
4230552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4231552f7358SJed Brown {
4232552f7358SJed Brown   PetscFunctionBegin;
4233552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4234d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4235d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4236d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
42379566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4238d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4239552f7358SJed Brown   PetscFunctionReturn(0);
4240552f7358SJed Brown }
4241552f7358SJed Brown 
4242552f7358SJed Brown /*@C
4243552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4244552f7358SJed Brown 
4245552f7358SJed Brown   Not Collective
4246552f7358SJed Brown 
4247552f7358SJed Brown   Input Parameters:
4248552f7358SJed Brown + dm - The DMPlex object
4249552f7358SJed Brown . numPoints - The number of input points for the join
4250552f7358SJed Brown - points - The input points
4251552f7358SJed Brown 
4252552f7358SJed Brown   Output Parameters:
4253552f7358SJed Brown + numCoveredPoints - The number of points in the join
4254552f7358SJed Brown - coveredPoints - The points in the join
4255552f7358SJed Brown 
42563813dfbdSMatthew G Knepley   Fortran Notes:
42573813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42583813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42593813dfbdSMatthew G Knepley 
42603813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42613813dfbdSMatthew G Knepley 
4262552f7358SJed Brown   Level: intermediate
4263552f7358SJed Brown 
4264552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet()
4265552f7358SJed Brown @*/
4266552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4267552f7358SJed Brown {
4268552f7358SJed Brown   PetscInt      *offsets, **closures;
4269552f7358SJed Brown   PetscInt      *join[2];
4270552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
427124c766afSToby Isaac   PetscInt       p, d, c, m, ms;
4272552f7358SJed Brown 
4273552f7358SJed Brown   PetscFunctionBegin;
4274552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
427548bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
427648bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
427748bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4278552f7358SJed Brown 
42799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
42809566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
42819566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
4282*6302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
428324c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
42849566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
42859566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4286552f7358SJed Brown 
4287552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4288552f7358SJed Brown     PetscInt closureSize;
4289552f7358SJed Brown 
42909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
42910d644c17SKarl Rupp 
4292552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
4293552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
4294552f7358SJed Brown       PetscInt pStart, pEnd, i;
4295552f7358SJed Brown 
42969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4297552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
4298552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4299552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
4300552f7358SJed Brown           break;
4301552f7358SJed Brown         }
4302552f7358SJed Brown       }
4303552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
4304552f7358SJed Brown     }
43052c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offsets[p*(depth+2)+depth+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize);
4306552f7358SJed Brown   }
4307552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
4308552f7358SJed Brown     PetscInt dof;
4309552f7358SJed Brown 
4310552f7358SJed Brown     /* Copy in support of first point */
4311552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4312552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4313552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4314552f7358SJed Brown     }
4315552f7358SJed Brown     /* Check each successive cone */
4316552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4317552f7358SJed Brown       PetscInt newJoinSize = 0;
4318552f7358SJed Brown 
4319552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4320552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4321552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4322552f7358SJed Brown 
4323552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4324552f7358SJed Brown           if (point == join[i][m]) {
4325552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4326552f7358SJed Brown             break;
4327552f7358SJed Brown           }
4328552f7358SJed Brown         }
4329552f7358SJed Brown       }
4330552f7358SJed Brown       joinSize = newJoinSize;
4331552f7358SJed Brown       i        = 1-i;
4332552f7358SJed Brown     }
4333552f7358SJed Brown     if (joinSize) break;
4334552f7358SJed Brown   }
4335552f7358SJed Brown   *numCoveredPoints = joinSize;
4336552f7358SJed Brown   *coveredPoints    = join[i];
4337552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
43389566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
4339552f7358SJed Brown   }
43409566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
43419566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
4342*6302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i]));
4343552f7358SJed Brown   PetscFunctionReturn(0);
4344552f7358SJed Brown }
4345552f7358SJed Brown 
4346552f7358SJed Brown /*@C
4347552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4348552f7358SJed Brown 
4349552f7358SJed Brown   Not Collective
4350552f7358SJed Brown 
4351552f7358SJed Brown   Input Parameters:
4352552f7358SJed Brown + dm - The DMPlex object
4353552f7358SJed Brown . numPoints - The number of input points for the meet
4354552f7358SJed Brown - points - The input points
4355552f7358SJed Brown 
4356552f7358SJed Brown   Output Parameters:
4357552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4358552f7358SJed Brown - coveredPoints - The points in the meet
4359552f7358SJed Brown 
4360552f7358SJed Brown   Level: intermediate
4361552f7358SJed Brown 
4362552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4363552f7358SJed Brown 
43643813dfbdSMatthew G Knepley   Fortran Notes:
43653813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43663813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43673813dfbdSMatthew G Knepley 
43683813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43693813dfbdSMatthew G Knepley 
4370552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin()
4371552f7358SJed Brown @*/
4372552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4373552f7358SJed Brown {
4374552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4375552f7358SJed Brown   PetscInt      *meet[2];
4376552f7358SJed Brown   PetscInt       meetSize, i = 0;
4377552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4378*6302a7fbSVaclav Hapla   PetscInt       maxConeSize;
4379552f7358SJed Brown 
4380552f7358SJed Brown   PetscFunctionBegin;
4381552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4382dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4383dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4384064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
4385*6302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
4386*6302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
4387*6302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4388552f7358SJed Brown   /* Copy in cone of first point */
43899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
43909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4391552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4392552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4393552f7358SJed Brown   }
4394552f7358SJed Brown   /* Check each successive cone */
4395552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4396552f7358SJed Brown     PetscInt newMeetSize = 0;
4397552f7358SJed Brown 
43989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
43999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4400552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4401552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4402552f7358SJed Brown 
4403552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4404552f7358SJed Brown         if (point == meet[i][m]) {
4405552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4406552f7358SJed Brown           break;
4407552f7358SJed Brown         }
4408552f7358SJed Brown       }
4409552f7358SJed Brown     }
4410552f7358SJed Brown     meetSize = newMeetSize;
4411552f7358SJed Brown     i        = 1-i;
4412552f7358SJed Brown   }
4413552f7358SJed Brown   *numCoveringPoints = meetSize;
4414552f7358SJed Brown   *coveringPoints    = meet[i];
4415*6302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i]));
4416552f7358SJed Brown   PetscFunctionReturn(0);
4417552f7358SJed Brown }
4418552f7358SJed Brown 
4419552f7358SJed Brown /*@C
4420552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4421552f7358SJed Brown 
4422552f7358SJed Brown   Not Collective
4423552f7358SJed Brown 
4424552f7358SJed Brown   Input Parameters:
4425552f7358SJed Brown + dm - The DMPlex object
4426552f7358SJed Brown . numPoints - The number of input points for the meet
4427552f7358SJed Brown - points - The input points
4428552f7358SJed Brown 
4429552f7358SJed Brown   Output Parameters:
4430552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4431552f7358SJed Brown - coveredPoints - The points in the meet
4432552f7358SJed Brown 
4433552f7358SJed Brown   Level: intermediate
4434552f7358SJed Brown 
44353813dfbdSMatthew G Knepley   Fortran Notes:
44363813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44373813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44383813dfbdSMatthew G Knepley 
44393813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44403813dfbdSMatthew G Knepley 
4441552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin()
4442552f7358SJed Brown @*/
4443552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4444552f7358SJed Brown {
4445552f7358SJed Brown   PetscFunctionBegin;
4446552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4447d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4448d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4449d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
44509566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4451d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4452552f7358SJed Brown   PetscFunctionReturn(0);
4453552f7358SJed Brown }
4454552f7358SJed Brown 
4455552f7358SJed Brown /*@C
4456552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4457552f7358SJed Brown 
4458552f7358SJed Brown   Not Collective
4459552f7358SJed Brown 
4460552f7358SJed Brown   Input Parameters:
4461552f7358SJed Brown + dm - The DMPlex object
4462552f7358SJed Brown . numPoints - The number of input points for the meet
4463552f7358SJed Brown - points - The input points
4464552f7358SJed Brown 
4465552f7358SJed Brown   Output Parameters:
4466552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4467552f7358SJed Brown - coveredPoints - The points in the meet
4468552f7358SJed Brown 
4469552f7358SJed Brown   Level: intermediate
4470552f7358SJed Brown 
44713813dfbdSMatthew G Knepley   Fortran Notes:
44723813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44733813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44743813dfbdSMatthew G Knepley 
44753813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44763813dfbdSMatthew G Knepley 
4477552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin()
4478552f7358SJed Brown @*/
4479552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4480552f7358SJed Brown {
4481552f7358SJed Brown   PetscInt      *offsets, **closures;
4482552f7358SJed Brown   PetscInt      *meet[2];
4483552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
448424c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4485552f7358SJed Brown 
4486552f7358SJed Brown   PetscFunctionBegin;
4487552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4488dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4489dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4490064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4491552f7358SJed Brown 
44929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
44939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
44949566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
4495*6302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
449624c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
44979566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
44989566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4499552f7358SJed Brown 
4500552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4501552f7358SJed Brown     PetscInt closureSize;
4502552f7358SJed Brown 
45039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
45040d644c17SKarl Rupp 
4505552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4506552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4507552f7358SJed Brown       PetscInt pStart, pEnd, i;
4508552f7358SJed Brown 
45099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4510552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4511552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4512552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4513552f7358SJed Brown           break;
4514552f7358SJed Brown         }
4515552f7358SJed Brown       }
4516552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4517552f7358SJed Brown     }
45182c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offsets[p*(height+2)+height+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize);
4519552f7358SJed Brown   }
4520552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4521552f7358SJed Brown     PetscInt dof;
4522552f7358SJed Brown 
4523552f7358SJed Brown     /* Copy in cone of first point */
4524552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4525552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4526552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4527552f7358SJed Brown     }
4528552f7358SJed Brown     /* Check each successive cone */
4529552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4530552f7358SJed Brown       PetscInt newMeetSize = 0;
4531552f7358SJed Brown 
4532552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4533552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4534552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4535552f7358SJed Brown 
4536552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4537552f7358SJed Brown           if (point == meet[i][m]) {
4538552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4539552f7358SJed Brown             break;
4540552f7358SJed Brown           }
4541552f7358SJed Brown         }
4542552f7358SJed Brown       }
4543552f7358SJed Brown       meetSize = newMeetSize;
4544552f7358SJed Brown       i        = 1-i;
4545552f7358SJed Brown     }
4546552f7358SJed Brown     if (meetSize) break;
4547552f7358SJed Brown   }
4548552f7358SJed Brown   *numCoveredPoints = meetSize;
4549552f7358SJed Brown   *coveredPoints    = meet[i];
4550552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
45519566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
4552552f7358SJed Brown   }
45539566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45549566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
4555*6302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i]));
4556552f7358SJed Brown   PetscFunctionReturn(0);
4557552f7358SJed Brown }
4558552f7358SJed Brown 
45594e3744c5SMatthew G. Knepley /*@C
45604e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
45614e3744c5SMatthew G. Knepley 
45624e3744c5SMatthew G. Knepley   Not Collective
45634e3744c5SMatthew G. Knepley 
45644e3744c5SMatthew G. Knepley   Input Parameters:
45654e3744c5SMatthew G. Knepley + dmA - A DMPlex object
45664e3744c5SMatthew G. Knepley - dmB - A DMPlex object
45674e3744c5SMatthew G. Knepley 
45684e3744c5SMatthew G. Knepley   Output Parameters:
45694e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
45704e3744c5SMatthew G. Knepley 
45714e3744c5SMatthew G. Knepley   Level: intermediate
45724e3744c5SMatthew G. Knepley 
45734e3744c5SMatthew G. Knepley   Notes:
45744e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
45754e3744c5SMatthew G. Knepley 
45764e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone()
45774e3744c5SMatthew G. Knepley @*/
45784e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
45794e3744c5SMatthew G. Knepley {
45804e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
45814e3744c5SMatthew G. Knepley 
45824e3744c5SMatthew G. Knepley   PetscFunctionBegin;
45834e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
45844e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4585dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
45864e3744c5SMatthew G. Knepley 
45874e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
45889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
45899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
45904e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
45919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart,  &pEnd));
45929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
45934e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
45944e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
45954e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
45964e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
45974e3744c5SMatthew G. Knepley 
45989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
45999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
46009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
46019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
46029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
46039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
46044e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
46054e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
46064e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
46074e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
46084e3744c5SMatthew G. Knepley     }
46099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
46109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
46119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
46129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
46134e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
46144e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
46154e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
46164e3744c5SMatthew G. Knepley     }
46174e3744c5SMatthew G. Knepley   }
46184e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
46194e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
46204e3744c5SMatthew G. Knepley }
46214e3744c5SMatthew G. Knepley 
46227cd05799SMatthew G. Knepley /*@C
46237cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
46247cd05799SMatthew G. Knepley 
46257cd05799SMatthew G. Knepley   Not Collective
46267cd05799SMatthew G. Knepley 
46277cd05799SMatthew G. Knepley   Input Parameters:
46287cd05799SMatthew G. Knepley + dm         - The DMPlex
46297cd05799SMatthew G. Knepley . cellDim    - The cell dimension
46307cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
46317cd05799SMatthew G. Knepley 
46327cd05799SMatthew G. Knepley   Output Parameters:
46337cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
46347cd05799SMatthew G. Knepley 
46357cd05799SMatthew G. Knepley   Level: developer
46367cd05799SMatthew G. Knepley 
46377cd05799SMatthew G. Knepley   Notes:
46387cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
46397cd05799SMatthew G. Knepley 
46407cd05799SMatthew G. Knepley .seealso: DMPlexGetCone()
46417cd05799SMatthew G. Knepley @*/
464218ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4643a6dfd86eSKarl Rupp {
464482f516ccSBarry Smith   MPI_Comm       comm;
4645552f7358SJed Brown 
4646552f7358SJed Brown   PetscFunctionBegin;
46479566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
4648dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices,4);
4649552f7358SJed Brown   switch (cellDim) {
4650552f7358SJed Brown   case 0:
4651552f7358SJed Brown     *numFaceVertices = 0;
4652552f7358SJed Brown     break;
4653552f7358SJed Brown   case 1:
4654552f7358SJed Brown     *numFaceVertices = 1;
4655552f7358SJed Brown     break;
4656552f7358SJed Brown   case 2:
4657552f7358SJed Brown     switch (numCorners) {
465819436ca2SJed Brown     case 3: /* triangle */
465919436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4660552f7358SJed Brown       break;
466119436ca2SJed Brown     case 4: /* quadrilateral */
466219436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4663552f7358SJed Brown       break;
466419436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
466519436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4666552f7358SJed Brown       break;
466719436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
466819436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4669552f7358SJed Brown       break;
4670552f7358SJed Brown     default:
467198921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4672552f7358SJed Brown     }
4673552f7358SJed Brown     break;
4674552f7358SJed Brown   case 3:
4675552f7358SJed Brown     switch (numCorners) {
467619436ca2SJed Brown     case 4: /* tetradehdron */
467719436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4678552f7358SJed Brown       break;
467919436ca2SJed Brown     case 6: /* tet cohesive cells */
468019436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4681552f7358SJed Brown       break;
468219436ca2SJed Brown     case 8: /* hexahedron */
468319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4684552f7358SJed Brown       break;
468519436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
468619436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4687552f7358SJed Brown       break;
468819436ca2SJed Brown     case 10: /* quadratic tetrahedron */
468919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4690552f7358SJed Brown       break;
469119436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
469219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4693552f7358SJed Brown       break;
469419436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
469519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4696552f7358SJed Brown       break;
469719436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
469819436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4699552f7358SJed Brown       break;
4700552f7358SJed Brown     default:
470198921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4702552f7358SJed Brown     }
4703552f7358SJed Brown     break;
4704552f7358SJed Brown   default:
470598921bdaSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim);
4706552f7358SJed Brown   }
4707552f7358SJed Brown   PetscFunctionReturn(0);
4708552f7358SJed Brown }
4709552f7358SJed Brown 
4710552f7358SJed Brown /*@
4711aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4712552f7358SJed Brown 
4713552f7358SJed Brown   Not Collective
4714552f7358SJed Brown 
4715aa50250dSMatthew G. Knepley   Input Parameter:
4716552f7358SJed Brown . dm    - The DMPlex object
4717552f7358SJed Brown 
4718aa50250dSMatthew G. Knepley   Output Parameter:
4719aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4720552f7358SJed Brown 
4721552f7358SJed Brown   Level: developer
4722552f7358SJed Brown 
4723dc287ab2SVaclav Hapla .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(),
4724aa50250dSMatthew G. Knepley @*/
4725aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4726aa50250dSMatthew G. Knepley {
4727aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4728aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4729aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4730c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4731aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4732aa50250dSMatthew G. Knepley }
4733aa50250dSMatthew G. Knepley 
4734aa50250dSMatthew G. Knepley /*@
4735aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4736aa50250dSMatthew G. Knepley 
4737aa50250dSMatthew G. Knepley   Not Collective
4738aa50250dSMatthew G. Knepley 
4739aa50250dSMatthew G. Knepley   Input Parameter:
4740aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4741aa50250dSMatthew G. Knepley 
4742aa50250dSMatthew G. Knepley   Output Parameter:
4743aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4744aa50250dSMatthew G. Knepley 
4745aa50250dSMatthew G. Knepley   Level: developer
4746552f7358SJed Brown 
4747b1bb481bSMatthew Knepley   Notes:
4748b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4749dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4750dc287ab2SVaclav Hapla   An empty mesh gives -1.
4751b1bb481bSMatthew Knepley 
4752dc287ab2SVaclav Hapla .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize()
4753552f7358SJed Brown @*/
4754552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4755552f7358SJed Brown {
4756aa50250dSMatthew G. Knepley   DMLabel        label;
4757aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4758552f7358SJed Brown 
4759552f7358SJed Brown   PetscFunctionBegin;
4760552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4761dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
47629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
47639566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelGetNumValues(label, &d));
4764552f7358SJed Brown   *depth = d-1;
4765552f7358SJed Brown   PetscFunctionReturn(0);
4766552f7358SJed Brown }
4767552f7358SJed Brown 
4768552f7358SJed Brown /*@
4769552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4770552f7358SJed Brown 
4771552f7358SJed Brown   Not Collective
4772552f7358SJed Brown 
4773552f7358SJed Brown   Input Parameters:
4774552f7358SJed Brown + dm           - The DMPlex object
4775552f7358SJed Brown - stratumValue - The requested depth
4776552f7358SJed Brown 
4777552f7358SJed Brown   Output Parameters:
4778552f7358SJed Brown + start - The first point at this depth
4779552f7358SJed Brown - end   - One beyond the last point at this depth
4780552f7358SJed Brown 
4781647867b2SJed Brown   Notes:
4782647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4783647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4784647867b2SJed Brown   higher dimension, e.g., "edges".
4785647867b2SJed Brown 
4786552f7358SJed Brown   Level: developer
4787552f7358SJed Brown 
4788dc287ab2SVaclav Hapla .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate()
4789552f7358SJed Brown @*/
47900adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
47910adebc6cSBarry Smith {
4792aa50250dSMatthew G. Knepley   DMLabel        label;
479363d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4794552f7358SJed Brown 
4795552f7358SJed Brown   PetscFunctionBegin;
4796552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4797dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4798dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
47999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48000d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
480163d1a920SMatthew G. Knepley   if (stratumValue < 0) {
480263d1a920SMatthew G. Knepley     if (start) *start = pStart;
480363d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
480463d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4805552f7358SJed Brown   }
48069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
480728b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48089566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(label, stratumValue, start, end));
4809552f7358SJed Brown   PetscFunctionReturn(0);
4810552f7358SJed Brown }
4811552f7358SJed Brown 
4812552f7358SJed Brown /*@
4813552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4814552f7358SJed Brown 
4815552f7358SJed Brown   Not Collective
4816552f7358SJed Brown 
4817552f7358SJed Brown   Input Parameters:
4818552f7358SJed Brown + dm           - The DMPlex object
4819552f7358SJed Brown - stratumValue - The requested height
4820552f7358SJed Brown 
4821552f7358SJed Brown   Output Parameters:
4822552f7358SJed Brown + start - The first point at this height
4823552f7358SJed Brown - end   - One beyond the last point at this height
4824552f7358SJed Brown 
4825647867b2SJed Brown   Notes:
4826647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4827647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4828647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4829647867b2SJed Brown 
4830552f7358SJed Brown   Level: developer
4831552f7358SJed Brown 
48323dc9a465SVaclav Hapla .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight()
4833552f7358SJed Brown @*/
48340adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
48350adebc6cSBarry Smith {
4836aa50250dSMatthew G. Knepley   DMLabel        label;
483763d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4838552f7358SJed Brown 
4839552f7358SJed Brown   PetscFunctionBegin;
4840552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4841dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4842dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48440d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
484563d1a920SMatthew G. Knepley   if (stratumValue < 0) {
484663d1a920SMatthew G. Knepley     if (start) *start = pStart;
484763d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
484863d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4849552f7358SJed Brown   }
48509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
485128b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48529566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
48539566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end));
4854552f7358SJed Brown   PetscFunctionReturn(0);
4855552f7358SJed Brown }
4856552f7358SJed Brown 
4857ba2698f1SMatthew G. Knepley /*@
4858ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4859ba2698f1SMatthew G. Knepley 
4860ba2698f1SMatthew G. Knepley   Not Collective
4861ba2698f1SMatthew G. Knepley 
4862d8d19677SJose E. Roman   Input Parameters:
4863ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4864ba2698f1SMatthew G. Knepley - point - The point
4865ba2698f1SMatthew G. Knepley 
4866ba2698f1SMatthew G. Knepley   Output Parameter:
4867ba2698f1SMatthew G. Knepley . depth - The depth of the point
4868ba2698f1SMatthew G. Knepley 
4869ba2698f1SMatthew G. Knepley   Level: intermediate
4870ba2698f1SMatthew G. Knepley 
48713dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight()
4872ba2698f1SMatthew G. Knepley @*/
4873ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4874ba2698f1SMatthew G. Knepley {
4875ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4876ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
487740a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
48789566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
4879ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4880ba2698f1SMatthew G. Knepley }
4881ba2698f1SMatthew G. Knepley 
4882ba2698f1SMatthew G. Knepley /*@
48830c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
48840c0a32dcSVaclav Hapla 
48850c0a32dcSVaclav Hapla   Not Collective
48860c0a32dcSVaclav Hapla 
4887d8d19677SJose E. Roman   Input Parameters:
48880c0a32dcSVaclav Hapla + dm    - The DMPlex object
48890c0a32dcSVaclav Hapla - point - The point
48900c0a32dcSVaclav Hapla 
48910c0a32dcSVaclav Hapla   Output Parameter:
48920c0a32dcSVaclav Hapla . height - The height of the point
48930c0a32dcSVaclav Hapla 
48940c0a32dcSVaclav Hapla   Level: intermediate
48950c0a32dcSVaclav Hapla 
48963dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth()
48970c0a32dcSVaclav Hapla @*/
48980c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
48990c0a32dcSVaclav Hapla {
49000c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
49010c0a32dcSVaclav Hapla 
49020c0a32dcSVaclav Hapla   PetscFunctionBegin;
49030c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49040c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
49059566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
49069566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
49070c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
49080c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
49090c0a32dcSVaclav Hapla }
49100c0a32dcSVaclav Hapla 
49110c0a32dcSVaclav Hapla /*@
4912ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4913ba2698f1SMatthew G. Knepley 
4914ba2698f1SMatthew G. Knepley   Not Collective
4915ba2698f1SMatthew G. Knepley 
4916ba2698f1SMatthew G. Knepley   Input Parameter:
4917ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4918ba2698f1SMatthew G. Knepley 
4919ba2698f1SMatthew G. Knepley   Output Parameter:
4920ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4921ba2698f1SMatthew G. Knepley 
4922412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4923412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4924412e9a14SMatthew G. Knepley 
4925ba2698f1SMatthew G. Knepley   Level: developer
4926ba2698f1SMatthew G. Knepley 
4927dc287ab2SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel()
4928ba2698f1SMatthew G. Knepley @*/
4929ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4930ba2698f1SMatthew G. Knepley {
4931ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4932ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4933ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
49349566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
4935ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4936ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4937ba2698f1SMatthew G. Knepley }
4938ba2698f1SMatthew G. Knepley 
4939ba2698f1SMatthew G. Knepley /*@
4940ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4941ba2698f1SMatthew G. Knepley 
4942ba2698f1SMatthew G. Knepley   Not Collective
4943ba2698f1SMatthew G. Knepley 
4944d8d19677SJose E. Roman   Input Parameters:
4945ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4946ba2698f1SMatthew G. Knepley - cell - The cell
4947ba2698f1SMatthew G. Knepley 
4948ba2698f1SMatthew G. Knepley   Output Parameter:
4949ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4950ba2698f1SMatthew G. Knepley 
4951ba2698f1SMatthew G. Knepley   Level: intermediate
4952ba2698f1SMatthew G. Knepley 
4953ba2698f1SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth()
4954ba2698f1SMatthew G. Knepley @*/
4955ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4956ba2698f1SMatthew G. Knepley {
4957ba2698f1SMatthew G. Knepley   DMLabel        label;
4958ba2698f1SMatthew G. Knepley   PetscInt       ct;
4959ba2698f1SMatthew G. Knepley 
4960ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4961ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4962ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
49639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
49649566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, cell, &ct));
49652c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell);
4966ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
4967ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4968ba2698f1SMatthew G. Knepley }
4969ba2698f1SMatthew G. Knepley 
4970412e9a14SMatthew G. Knepley /*@
4971412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
4972412e9a14SMatthew G. Knepley 
4973412e9a14SMatthew G. Knepley   Not Collective
4974412e9a14SMatthew G. Knepley 
4975412e9a14SMatthew G. Knepley   Input Parameters:
4976412e9a14SMatthew G. Knepley + dm   - The DMPlex object
4977412e9a14SMatthew G. Knepley . cell - The cell
4978412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
4979412e9a14SMatthew G. Knepley 
4980412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
4981412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
4982412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
4983412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
4984412e9a14SMatthew G. Knepley 
4985412e9a14SMatthew G. Knepley   Level: advanced
4986412e9a14SMatthew G. Knepley 
4987412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel()
4988412e9a14SMatthew G. Knepley @*/
4989412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
4990412e9a14SMatthew G. Knepley {
4991412e9a14SMatthew G. Knepley   DMLabel        label;
4992412e9a14SMatthew G. Knepley 
4993412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4994412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
49969566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
4997412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4998412e9a14SMatthew G. Knepley }
4999412e9a14SMatthew G. Knepley 
50000adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
50010adebc6cSBarry Smith {
5002efe440bfSMatthew G. Knepley   PetscSection   section, s;
5003efe440bfSMatthew G. Knepley   Mat            m;
50043e922f36SToby Isaac   PetscInt       maxHeight;
5005552f7358SJed Brown 
5006552f7358SJed Brown   PetscFunctionBegin;
50079566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
50089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
50099566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
50109566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
50119566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
50129566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
50139566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
50149566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
50159566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
50169566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
50179566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
50188f4c458bSMatthew G. Knepley 
50199566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
50209566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5021552f7358SJed Brown   PetscFunctionReturn(0);
5022552f7358SJed Brown }
5023552f7358SJed Brown 
5024f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5025f19dbd58SToby Isaac {
5026f19dbd58SToby Isaac   Vec            coordsLocal;
5027f19dbd58SToby Isaac   DM             coordsDM;
5028f19dbd58SToby Isaac 
5029f19dbd58SToby Isaac   PetscFunctionBegin;
5030f19dbd58SToby Isaac   *field = NULL;
50319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm,&coordsLocal));
50329566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm,&coordsDM));
5033f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
50349566063dSJacob Faibussowitsch     PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5035f19dbd58SToby Isaac   }
5036f19dbd58SToby Isaac   PetscFunctionReturn(0);
5037f19dbd58SToby Isaac }
5038f19dbd58SToby Isaac 
50397cd05799SMatthew G. Knepley /*@C
50407cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
50417cd05799SMatthew G. Knepley 
50427cd05799SMatthew G. Knepley   Not Collective
50437cd05799SMatthew G. Knepley 
50447cd05799SMatthew G. Knepley   Input Parameters:
50457cd05799SMatthew G. Knepley . dm        - The DMPlex object
50467cd05799SMatthew G. Knepley 
50477cd05799SMatthew G. Knepley   Output Parameter:
50487cd05799SMatthew G. Knepley . section - The PetscSection object
50497cd05799SMatthew G. Knepley 
50507cd05799SMatthew G. Knepley   Level: developer
50517cd05799SMatthew G. Knepley 
50527cd05799SMatthew G. Knepley .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations()
50537cd05799SMatthew G. Knepley @*/
50540adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50550adebc6cSBarry Smith {
5056552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5057552f7358SJed Brown 
5058552f7358SJed Brown   PetscFunctionBegin;
5059552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5060552f7358SJed Brown   if (section) *section = mesh->coneSection;
5061552f7358SJed Brown   PetscFunctionReturn(0);
5062552f7358SJed Brown }
5063552f7358SJed Brown 
50647cd05799SMatthew G. Knepley /*@C
50657cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
50667cd05799SMatthew G. Knepley 
50677cd05799SMatthew G. Knepley   Not Collective
50687cd05799SMatthew G. Knepley 
50697cd05799SMatthew G. Knepley   Input Parameters:
50707cd05799SMatthew G. Knepley . dm        - The DMPlex object
50717cd05799SMatthew G. Knepley 
50727cd05799SMatthew G. Knepley   Output Parameter:
50737cd05799SMatthew G. Knepley . section - The PetscSection object
50747cd05799SMatthew G. Knepley 
50757cd05799SMatthew G. Knepley   Level: developer
50767cd05799SMatthew G. Knepley 
50777cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
50787cd05799SMatthew G. Knepley @*/
50798cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
50808cb4d582SMatthew G. Knepley {
50818cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
50828cb4d582SMatthew G. Knepley 
50838cb4d582SMatthew G. Knepley   PetscFunctionBegin;
50848cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50858cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
50868cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
50878cb4d582SMatthew G. Knepley }
50888cb4d582SMatthew G. Knepley 
50897cd05799SMatthew G. Knepley /*@C
50907cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
50917cd05799SMatthew G. Knepley 
50927cd05799SMatthew G. Knepley   Not Collective
50937cd05799SMatthew G. Knepley 
50947cd05799SMatthew G. Knepley   Input Parameters:
50957cd05799SMatthew G. Knepley . dm        - The DMPlex object
50967cd05799SMatthew G. Knepley 
50977cd05799SMatthew G. Knepley   Output Parameter:
50987cd05799SMatthew G. Knepley . cones - The cone for each point
50997cd05799SMatthew G. Knepley 
51007cd05799SMatthew G. Knepley   Level: developer
51017cd05799SMatthew G. Knepley 
51027cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
51037cd05799SMatthew G. Knepley @*/
5104a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5105a6dfd86eSKarl Rupp {
5106552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5107552f7358SJed Brown 
5108552f7358SJed Brown   PetscFunctionBegin;
5109552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5110552f7358SJed Brown   if (cones) *cones = mesh->cones;
5111552f7358SJed Brown   PetscFunctionReturn(0);
5112552f7358SJed Brown }
5113552f7358SJed Brown 
51147cd05799SMatthew G. Knepley /*@C
51157cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
51167cd05799SMatthew G. Knepley 
51177cd05799SMatthew G. Knepley   Not Collective
51187cd05799SMatthew G. Knepley 
51197cd05799SMatthew G. Knepley   Input Parameters:
51207cd05799SMatthew G. Knepley . dm        - The DMPlex object
51217cd05799SMatthew G. Knepley 
51227cd05799SMatthew G. Knepley   Output Parameter:
5123b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
51247cd05799SMatthew G. Knepley 
51257cd05799SMatthew G. Knepley   Level: developer
51267cd05799SMatthew G. Knepley 
5127b5a892a1SMatthew G. Knepley   Notes:
5128b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5129b5a892a1SMatthew G. Knepley 
5130b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5131b5a892a1SMatthew G. Knepley 
5132b5a892a1SMatthew G. Knepley .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation()
51337cd05799SMatthew G. Knepley @*/
5134a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5135a6dfd86eSKarl Rupp {
5136552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5137552f7358SJed Brown 
5138552f7358SJed Brown   PetscFunctionBegin;
5139552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5140552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5141552f7358SJed Brown   PetscFunctionReturn(0);
5142552f7358SJed Brown }
5143552f7358SJed Brown 
5144552f7358SJed Brown /******************************** FEM Support **********************************/
5145552f7358SJed Brown 
51469e8305c2SJed Brown /*
51479e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
51489e8305c2SJed Brown  representing a line in the section.
51499e8305c2SJed Brown */
51509e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
51519e8305c2SJed Brown {
51529e8305c2SJed Brown   PetscFunctionBeginHot;
51539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5154a433471fSStefano Zampini   if (line < 0) {
5155a433471fSStefano Zampini     *k = 0;
5156a433471fSStefano Zampini     *Nc = 0;
5157a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
51589e8305c2SJed Brown     *k = 1;
51599e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
51609e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
51619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
51629e8305c2SJed Brown     *k = *k / *Nc + 1;
51639e8305c2SJed Brown   }
51649e8305c2SJed Brown   PetscFunctionReturn(0);
51659e8305c2SJed Brown }
51669e8305c2SJed Brown 
5167a4355906SMatthew Knepley /*@
5168bc1eb3faSJed Brown 
5169bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5170bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
51711bb6d2a8SBarry Smith   section provided (or the section of the DM).
5172a4355906SMatthew Knepley 
5173a4355906SMatthew Knepley   Input Parameters:
5174a4355906SMatthew Knepley + dm      - The DM
5175a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5176a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5177a4355906SMatthew Knepley 
5178a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5179a4355906SMatthew Knepley   degree of the basis.
5180a4355906SMatthew Knepley 
5181bc1eb3faSJed Brown   Example:
5182bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5183bc1eb3faSJed Brown .vb
5184bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5185bc1eb3faSJed Brown 
5186bc1eb3faSJed Brown   v4 -- e6 -- v3
5187bc1eb3faSJed Brown   |           |
5188bc1eb3faSJed Brown   e7    c0    e8
5189bc1eb3faSJed Brown   |           |
5190bc1eb3faSJed Brown   v1 -- e5 -- v2
5191bc1eb3faSJed Brown .ve
5192bc1eb3faSJed Brown 
5193bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5194bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5195bc1eb3faSJed Brown .vb
5196bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5197bc1eb3faSJed Brown     v1 -> [4]
5198bc1eb3faSJed Brown     ...
5199bc1eb3faSJed Brown     e5 -> [8, 9]
5200bc1eb3faSJed Brown .ve
5201bc1eb3faSJed Brown 
5202bc1eb3faSJed Brown   which corresponds to the dofs
5203bc1eb3faSJed Brown .vb
5204bc1eb3faSJed Brown     6   10  11  7
5205bc1eb3faSJed Brown     13  2   3   15
5206bc1eb3faSJed Brown     12  0   1   14
5207bc1eb3faSJed Brown     4   8   9   5
5208bc1eb3faSJed Brown .ve
5209bc1eb3faSJed Brown 
5210bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5211bc1eb3faSJed Brown .vb
5212bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5213bc1eb3faSJed Brown .ve
5214bc1eb3faSJed Brown 
5215bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5216bc1eb3faSJed Brown .vb
5217bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5218bc1eb3faSJed Brown .ve
5219bc1eb3faSJed Brown 
5220a4355906SMatthew Knepley   Level: developer
5221a4355906SMatthew Knepley 
52229df75925SJed Brown .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection()
5223a4355906SMatthew Knepley @*/
5224bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
52253194fc30SMatthew G. Knepley {
52267391a63aSMatthew G. Knepley   DMLabel        label;
5227bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
52289e8305c2SJed Brown   PetscBool      vertexchart;
52293194fc30SMatthew G. Knepley 
52303194fc30SMatthew G. Knepley   PetscFunctionBegin;
52319566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5232a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5233a433471fSStefano Zampini   if (point < 0) {
5234a433471fSStefano Zampini     PetscInt sStart,sEnd;
5235a433471fSStefano Zampini 
52369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5237a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
5238a433471fSStefano Zampini   }
52399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
52409566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
52419566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
52427391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
52437391a63aSMatthew G. Knepley   else if  (depth == dim) {
52447391a63aSMatthew G. Knepley     const PetscInt *cone;
52457391a63aSMatthew G. Knepley 
52469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5247d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5248d4e6627bSStefano Zampini     else if (dim == 3) {
5249d4e6627bSStefano Zampini       const PetscInt *cone2;
52509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5251d4e6627bSStefano Zampini       eStart = cone2[0];
525298921bdaSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim);
52532c71b3e2SJacob Faibussowitsch   } else PetscCheckFalse(depth >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim);
52549e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
52559e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
52569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd));
52579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section,&cStart,&cEnd));
5258796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5259796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5260796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
52619e8305c2SJed Brown   }
52629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5263bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
5264bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5265bb197d40SJed Brown     PetscInt *perm;
5266bb197d40SJed Brown 
52673194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
52689566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5269bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
52703194fc30SMatthew G. Knepley     }
52719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
52723194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5273bb197d40SJed Brown       switch (d) {
5274babf31e0SJed Brown       case 1:
52759566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5276babf31e0SJed Brown         /*
5277babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5278babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5279babf31e0SJed Brown          */
5280babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
5281babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
5282babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
5283babf31e0SJed Brown         foffset = offset;
5284babf31e0SJed Brown         break;
528589eabcffSMatthew G. Knepley       case 2:
52863194fc30SMatthew 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} */
52879566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
52883194fc30SMatthew G. Knepley         /* The SEM order is
52893194fc30SMatthew G. Knepley 
52903194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
529189eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
52923194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
52933194fc30SMatthew G. Knepley          */
52943194fc30SMatthew G. Knepley         {
52953194fc30SMatthew G. Knepley           const PetscInt of   = 0;
52963194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
52973194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
52983194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
52993194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
53003194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
53013194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
53023194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
53033194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
53043194fc30SMatthew G. Knepley           PetscInt       o;
53053194fc30SMatthew G. Knepley 
53063194fc30SMatthew G. Knepley           /* bottom */
53073194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
53083194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53093194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
53103194fc30SMatthew G. Knepley           /* middle */
53113194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
53123194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
53133194fc30SMatthew G. Knepley             for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53143194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
53153194fc30SMatthew G. Knepley           }
53163194fc30SMatthew G. Knepley           /* top */
53173194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
53183194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53193194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
53203194fc30SMatthew G. Knepley           foffset = offset;
53213194fc30SMatthew G. Knepley         }
532289eabcffSMatthew G. Knepley         break;
532389eabcffSMatthew G. Knepley       case 3:
532489eabcffSMatthew G. Knepley         /* The original hex closure is
532589eabcffSMatthew G. Knepley 
532689eabcffSMatthew G. Knepley          {c,
532789eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
532889eabcffSMatthew 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,
532989eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
533089eabcffSMatthew G. Knepley          */
53319566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
533289eabcffSMatthew G. Knepley         /* The SEM order is
533389eabcffSMatthew G. Knepley          Bottom Slice
533489eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
533589eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
533689eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
533789eabcffSMatthew G. Knepley 
533889eabcffSMatthew G. Knepley          Middle Slice (j)
533989eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
534089eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
534189eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
534289eabcffSMatthew G. Knepley 
534389eabcffSMatthew G. Knepley          Top Slice
534489eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
534589eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
534689eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
534789eabcffSMatthew G. Knepley          */
534889eabcffSMatthew G. Knepley         {
534989eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
535089eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
535189eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
535289eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
535389eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
535489eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
535589eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
535689eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
535789eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
535889eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
535989eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
536089eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
536189eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
536289eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
536389eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
536489eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
536589eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
536689eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
536789eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
536889eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
536989eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
537089eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
537189eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
537289eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
537389eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
537489eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
537589eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
537689eabcffSMatthew G. Knepley           PetscInt       o, n;
537789eabcffSMatthew G. Knepley 
537889eabcffSMatthew G. Knepley           /* Bottom Slice */
537989eabcffSMatthew G. Knepley           /*   bottom */
538089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
538189eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
538289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
538389eabcffSMatthew G. Knepley           /*   middle */
538489eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
538589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5386316b7f87SMax Rietmann             for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;}
538789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
53883194fc30SMatthew G. Knepley           }
538989eabcffSMatthew G. Knepley           /*   top */
539089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
539189eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
539289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
539389eabcffSMatthew G. Knepley 
539489eabcffSMatthew G. Knepley           /* Middle Slice */
539589eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
539689eabcffSMatthew G. Knepley             /*   bottom */
539789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
539889eabcffSMatthew G. Knepley             for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
539989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
540089eabcffSMatthew G. Knepley             /*   middle */
540189eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
540289eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
540389eabcffSMatthew G. Knepley               for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset;
540489eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
540589eabcffSMatthew G. Knepley             }
540689eabcffSMatthew G. Knepley             /*   top */
540789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
540889eabcffSMatthew G. Knepley             for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
540989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
541089eabcffSMatthew G. Knepley           }
541189eabcffSMatthew G. Knepley 
541289eabcffSMatthew G. Knepley           /* Top Slice */
541389eabcffSMatthew G. Knepley           /*   bottom */
541489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
541589eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
541689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
541789eabcffSMatthew G. Knepley           /*   middle */
541889eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
541989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
542089eabcffSMatthew G. Knepley             for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset;
542189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
542289eabcffSMatthew G. Knepley           }
542389eabcffSMatthew G. Knepley           /*   top */
542489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
542589eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
542689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
542789eabcffSMatthew G. Knepley 
542889eabcffSMatthew G. Knepley           foffset = offset;
542989eabcffSMatthew G. Knepley         }
543089eabcffSMatthew G. Knepley         break;
543198921bdaSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d);
543289eabcffSMatthew G. Knepley       }
543389eabcffSMatthew G. Knepley     }
54342c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size);
54353194fc30SMatthew G. Knepley     /* Check permutation */
54363194fc30SMatthew G. Knepley     {
54373194fc30SMatthew G. Knepley       PetscInt *check;
54383194fc30SMatthew G. Knepley 
54399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
54402c71b3e2SJacob Faibussowitsch       for (i = 0; i < size; ++i) {check[i] = -1; PetscCheckFalse(perm[i] < 0 || perm[i] >= size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);}
54413194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54422c71b3e2SJacob Faibussowitsch       for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);}
54439566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
54443194fc30SMatthew G. Knepley     }
54459566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm));
5446a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5447a05c9aa3SJed Brown       PetscInt *loc_perm;
54489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size*2, &loc_perm));
5449a05c9aa3SJed Brown       for (PetscInt i=0; i<size; i++) {
5450a05c9aa3SJed Brown         loc_perm[i] = perm[i];
5451a05c9aa3SJed Brown         loc_perm[size+i] = size + perm[i];
5452a05c9aa3SJed Brown       }
54539566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm));
5454a05c9aa3SJed Brown     }
5455bb197d40SJed Brown   }
54563194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
54573194fc30SMatthew G. Knepley }
54583194fc30SMatthew G. Knepley 
5459e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5460e071409bSToby Isaac {
5461e071409bSToby Isaac   PetscDS        prob;
5462e071409bSToby Isaac   PetscInt       depth, Nf, h;
5463e071409bSToby Isaac   DMLabel        label;
5464e071409bSToby Isaac 
5465e071409bSToby Isaac   PetscFunctionBeginHot;
54669566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5467e071409bSToby Isaac   Nf      = prob->Nf;
5468e071409bSToby Isaac   label   = dm->depthLabel;
5469e071409bSToby Isaac   *dspace = NULL;
5470e071409bSToby Isaac   if (field < Nf) {
5471e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5472e071409bSToby Isaac 
5473e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5474e071409bSToby Isaac       PetscDualSpace dsp;
5475e071409bSToby Isaac 
54769566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp));
54779566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label,&depth));
54789566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label,point,&h));
5479e071409bSToby Isaac       h    = depth - 1 - h;
5480e071409bSToby Isaac       if (h) {
54819566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace));
5482e071409bSToby Isaac       } else {
5483e071409bSToby Isaac         *dspace = dsp;
5484e071409bSToby Isaac       }
5485e071409bSToby Isaac     }
5486e071409bSToby Isaac   }
5487e071409bSToby Isaac   PetscFunctionReturn(0);
5488e071409bSToby Isaac }
5489e071409bSToby Isaac 
54909fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5491a6dfd86eSKarl Rupp {
5492552f7358SJed Brown   PetscScalar    *array, *vArray;
5493d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
54941a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5495552f7358SJed Brown 
54961b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
54979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
54989566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
54999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
55009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
55013f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
55029df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
55039df71ca4SMatthew G. Knepley       PetscInt dof;
5504d9917b9dSMatthew G. Knepley 
55059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
55069df71ca4SMatthew G. Knepley       size += dof;
55079df71ca4SMatthew G. Knepley     }
55089df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
55099df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
55102a3aaacfSMatthew G. Knepley       PetscInt       dof;
55115a1bb5cfSMatthew G. Knepley 
55125a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
55139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
55145a1bb5cfSMatthew G. Knepley       size += dof;
55155a1bb5cfSMatthew G. Knepley     }
55163f7cbbe7SMatthew G. Knepley     if (!values) {
55173f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
55183f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
55193f7cbbe7SMatthew G. Knepley     }
55209566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5521982e9ed1SMatthew G. Knepley   } else {
5522982e9ed1SMatthew G. Knepley     array = *values;
5523982e9ed1SMatthew G. Knepley   }
55249df71ca4SMatthew G. Knepley   size = 0;
55259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &vArray));
55269df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
55279df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
55289df71ca4SMatthew G. Knepley     PetscScalar *varr;
5529d9917b9dSMatthew G. Knepley 
55309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
55319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
55329df71ca4SMatthew G. Knepley     varr = &vArray[off];
55331a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
55341a271a75SMatthew G. Knepley       array[offset] = varr[d];
55359df71ca4SMatthew G. Knepley     }
55369df71ca4SMatthew G. Knepley     size += dof;
55379df71ca4SMatthew G. Knepley   }
55389df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
55399df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
55409df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
55415a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
55425a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
55435a1bb5cfSMatthew G. Knepley 
554452ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
55469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
55475a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55485a1bb5cfSMatthew G. Knepley     if (o >= 0) {
55491a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
55501a271a75SMatthew G. Knepley         array[offset] = varr[d];
55515a1bb5cfSMatthew G. Knepley       }
55525a1bb5cfSMatthew G. Knepley     } else {
55531a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
55541a271a75SMatthew G. Knepley         array[offset] = varr[d];
55555a1bb5cfSMatthew G. Knepley       }
55565a1bb5cfSMatthew G. Knepley     }
55579df71ca4SMatthew G. Knepley     size += dof;
55585a1bb5cfSMatthew G. Knepley   }
55599566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &vArray));
55609df71ca4SMatthew G. Knepley   if (!*values) {
55615a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
55625a1bb5cfSMatthew G. Knepley     *values = array;
55639df71ca4SMatthew G. Knepley   } else {
55642c71b3e2SJacob Faibussowitsch     PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
55658c312ff3SMatthew G. Knepley     *csize = size;
55669df71ca4SMatthew G. Knepley   }
55675a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
55685a1bb5cfSMatthew G. Knepley }
5569d9917b9dSMatthew G. Knepley 
557027f02ce8SMatthew G. Knepley /* Compress out points not in the section */
55719fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
557227f02ce8SMatthew G. Knepley {
557327f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
557427f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
557527f02ce8SMatthew G. Knepley 
55769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
557727f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
557827f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
557927f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
558027f02ce8SMatthew G. Knepley       points[q*2]   = r;
558127f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
558227f02ce8SMatthew G. Knepley       ++q;
558327f02ce8SMatthew G. Knepley     }
558427f02ce8SMatthew G. Knepley   }
558527f02ce8SMatthew G. Knepley   *numPoints = q;
558627f02ce8SMatthew G. Knepley   return 0;
558727f02ce8SMatthew G. Knepley }
558827f02ce8SMatthew G. Knepley 
558997529cf3SJed Brown /* Compressed closure does not apply closure permutation */
55901dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5591923c78e0SToby Isaac {
559227f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5593923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5594923c78e0SToby Isaac 
5595923c78e0SToby Isaac   PetscFunctionBeginHot;
55969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints));
559727f02ce8SMatthew G. Knepley   if (*clPoints) {
5598923c78e0SToby Isaac     PetscInt dof, off;
5599923c78e0SToby Isaac 
56009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
56019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
56029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5603923c78e0SToby Isaac     np   = dof/2;
5604923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
560527f02ce8SMatthew G. Knepley   } else {
56069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
56079566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5608923c78e0SToby Isaac   }
5609923c78e0SToby Isaac   *numPoints = np;
5610923c78e0SToby Isaac   *points    = pts;
5611923c78e0SToby Isaac   *clp       = cla;
5612923c78e0SToby Isaac   PetscFunctionReturn(0);
5613923c78e0SToby Isaac }
5614923c78e0SToby Isaac 
56151dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5616923c78e0SToby Isaac {
5617923c78e0SToby Isaac   PetscFunctionBeginHot;
5618923c78e0SToby Isaac   if (!*clPoints) {
56199566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5620923c78e0SToby Isaac   } else {
56219566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5622923c78e0SToby Isaac   }
5623923c78e0SToby Isaac   *numPoints = 0;
5624923c78e0SToby Isaac   *points    = NULL;
5625923c78e0SToby Isaac   *clSec     = NULL;
5626923c78e0SToby Isaac   *clPoints  = NULL;
5627923c78e0SToby Isaac   *clp       = NULL;
5628923c78e0SToby Isaac   PetscFunctionReturn(0);
5629923c78e0SToby Isaac }
5630923c78e0SToby Isaac 
56319fbee547SJacob 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[])
56321a271a75SMatthew G. Knepley {
56331a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
563497e99dd9SToby Isaac   const PetscInt    **perms = NULL;
563597e99dd9SToby Isaac   const PetscScalar **flips = NULL;
56361a271a75SMatthew G. Knepley 
56371a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5638fe02ba77SJed Brown   *size = 0;
56399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
564097e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
564197e99dd9SToby Isaac     const PetscInt    point = points[2*p];
564297e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
564397e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
56441a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
56451a271a75SMatthew G. Knepley     const PetscScalar *varr;
56461a271a75SMatthew G. Knepley 
56479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
56489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
56491a271a75SMatthew G. Knepley     varr = &vArray[off];
565097e99dd9SToby Isaac     if (clperm) {
565197e99dd9SToby Isaac       if (perm) {
565297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
56531a271a75SMatthew G. Knepley       } else {
565497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
565597e99dd9SToby Isaac       }
565697e99dd9SToby Isaac       if (flip) {
565797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
565897e99dd9SToby Isaac       }
565997e99dd9SToby Isaac     } else {
566097e99dd9SToby Isaac       if (perm) {
566197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
566297e99dd9SToby Isaac       } else {
566397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
566497e99dd9SToby Isaac       }
566597e99dd9SToby Isaac       if (flip) {
566697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
56671a271a75SMatthew G. Knepley       }
56681a271a75SMatthew G. Knepley     }
566997e99dd9SToby Isaac     offset += dof;
567097e99dd9SToby Isaac   }
56719566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
56721a271a75SMatthew G. Knepley   *size = offset;
56731a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
56741a271a75SMatthew G. Knepley }
56751a271a75SMatthew G. Knepley 
56769fbee547SJacob 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[])
56771a271a75SMatthew G. Knepley {
56781a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
56791a271a75SMatthew G. Knepley 
56801a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5681fe02ba77SJed Brown   *size = 0;
56821a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
568397e99dd9SToby Isaac     PetscInt          p;
568497e99dd9SToby Isaac     const PetscInt    **perms = NULL;
568597e99dd9SToby Isaac     const PetscScalar **flips = NULL;
56861a271a75SMatthew G. Knepley 
56879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
568897e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
568997e99dd9SToby Isaac       const PetscInt    point = points[2*p];
569097e99dd9SToby Isaac       PetscInt          fdof, foff, b;
56911a271a75SMatthew G. Knepley       const PetscScalar *varr;
569297e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
569397e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
56941a271a75SMatthew G. Knepley 
56959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
56969566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
56971a271a75SMatthew G. Knepley       varr = &vArray[foff];
569897e99dd9SToby Isaac       if (clperm) {
569997e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
570097e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
570197e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
57021a271a75SMatthew G. Knepley       } else {
570397e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
570497e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
570597e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
57061a271a75SMatthew G. Knepley       }
570797e99dd9SToby Isaac       offset += fdof;
57081a271a75SMatthew G. Knepley     }
57099566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
57101a271a75SMatthew G. Knepley   }
57111a271a75SMatthew G. Knepley   *size = offset;
57121a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57131a271a75SMatthew G. Knepley }
57141a271a75SMatthew G. Knepley 
5715552f7358SJed Brown /*@C
5716552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5717552f7358SJed Brown 
5718552f7358SJed Brown   Not collective
5719552f7358SJed Brown 
5720552f7358SJed Brown   Input Parameters:
5721552f7358SJed Brown + dm - The DM
5722552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5723552f7358SJed Brown . v - The local vector
57246b867d5aSJose E. Roman - point - The point in the DM
5725552f7358SJed Brown 
57266b867d5aSJose E. Roman   Input/Output Parameters:
57276b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
57286b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
57296b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
573022c1ee49SMatthew G. Knepley 
573122c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
573222c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
573322c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
573422c1ee49SMatthew G. Knepley $
573522c1ee49SMatthew G. Knepley $ A typical use could be
573622c1ee49SMatthew G. Knepley $
573722c1ee49SMatthew G. Knepley $  values = NULL;
57389566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
573922c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
574022c1ee49SMatthew G. Knepley $    <Compute on closure>
574122c1ee49SMatthew G. Knepley $  }
57429566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
574322c1ee49SMatthew G. Knepley $
574422c1ee49SMatthew G. Knepley $ or
574522c1ee49SMatthew G. Knepley $
574622c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
574722c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
574822c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
57499566063dSJacob Faibussowitsch $    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
575022c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
575122c1ee49SMatthew G. Knepley $      <Compute on closure>
575222c1ee49SMatthew G. Knepley $    }
575322c1ee49SMatthew G. Knepley $  }
575422c1ee49SMatthew G. Knepley $  PetscFree(values);
5755552f7358SJed Brown 
5756552f7358SJed Brown   Fortran Notes:
5757552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5758552f7358SJed Brown   include petsc.h90 in your code.
5759552f7358SJed Brown 
5760552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5761552f7358SJed Brown 
5762552f7358SJed Brown   Level: intermediate
5763552f7358SJed Brown 
5764552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5765552f7358SJed Brown @*/
5766552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5767552f7358SJed Brown {
5768552f7358SJed Brown   PetscSection       clSection;
5769d9917b9dSMatthew G. Knepley   IS                 clPoints;
5770552f7358SJed Brown   PetscInt          *points = NULL;
5771c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5772c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5773552f7358SJed Brown 
5774d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5775552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57769566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
57771a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
57781a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
57799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
57809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5781552f7358SJed Brown   if (depth == 1 && numFields < 2) {
57829566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5783552f7358SJed Brown     PetscFunctionReturn(0);
5784552f7358SJed Brown   }
57851a271a75SMatthew G. Knepley   /* Get points */
57869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5787c459fbc1SJed Brown   /* Get sizes */
5788c459fbc1SJed Brown   asize = 0;
5789c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5790c459fbc1SJed Brown     PetscInt dof;
57919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
57921a271a75SMatthew G. Knepley     asize += dof;
5793552f7358SJed Brown   }
5794c459fbc1SJed Brown   if (values) {
5795c459fbc1SJed Brown     const PetscScalar *vArray;
5796c459fbc1SJed Brown     PetscInt          size;
5797c459fbc1SJed Brown 
5798c459fbc1SJed Brown     if (*values) {
57992c71b3e2SJacob Faibussowitsch       PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize);
58009566063dSJacob Faibussowitsch     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
58019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm));
58029566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v, &vArray));
58031a271a75SMatthew G. Knepley     /* Get values */
58049566063dSJacob Faibussowitsch     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
58059566063dSJacob Faibussowitsch     else               PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
58062c71b3e2SJacob Faibussowitsch     PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size);
58071a271a75SMatthew G. Knepley     /* Cleanup array */
58089566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v, &vArray));
5809d0f6b257SMatthew G. Knepley   }
5810c459fbc1SJed Brown   if (csize) *csize = asize;
5811c459fbc1SJed Brown   /* Cleanup points */
58129566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5813552f7358SJed Brown   PetscFunctionReturn(0);
5814552f7358SJed Brown }
5815552f7358SJed Brown 
5816e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5817e5c487bfSMatthew G. Knepley {
5818e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5819e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5820e5c487bfSMatthew G. Knepley   IS                 clPoints;
5821e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5822e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5823e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5824c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5825c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5826e5c487bfSMatthew G. Knepley 
5827e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5828e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58299566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
5830e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5831e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
58339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
58349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5835e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
58369566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5837e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5838e5c487bfSMatthew G. Knepley   }
5839e5c487bfSMatthew G. Knepley   /* Get points */
58409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5841c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5842c459fbc1SJed Brown     PetscInt dof;
58439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
5844c459fbc1SJed Brown     clsize += dof;
5845c459fbc1SJed Brown   }
58469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm));
5847e5c487bfSMatthew G. Knepley   /* Filter points */
5848e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5849e5c487bfSMatthew G. Knepley     PetscInt dep;
5850e5c487bfSMatthew G. Knepley 
58519566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
5852e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5853e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5854e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5855e5c487bfSMatthew G. Knepley     ++Np;
5856e5c487bfSMatthew G. Knepley   }
5857e5c487bfSMatthew G. Knepley   /* Get array */
5858e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5859e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5860e5c487bfSMatthew G. Knepley 
5861e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
58629566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
5863e5c487bfSMatthew G. Knepley       asize += dof;
5864e5c487bfSMatthew G. Knepley     }
5865e5c487bfSMatthew G. Knepley     if (!values) {
58669566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5867e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5868e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5869e5c487bfSMatthew G. Knepley     }
58709566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
5871e5c487bfSMatthew G. Knepley   } else {
5872e5c487bfSMatthew G. Knepley     array = *values;
5873e5c487bfSMatthew G. Knepley   }
58749566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
5875e5c487bfSMatthew G. Knepley   /* Get values */
58769566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
58779566063dSJacob Faibussowitsch   else               PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
5878e5c487bfSMatthew G. Knepley   /* Cleanup points */
58799566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5880e5c487bfSMatthew G. Knepley   /* Cleanup array */
58819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
5882e5c487bfSMatthew G. Knepley   if (!*values) {
5883e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5884e5c487bfSMatthew G. Knepley     *values = array;
5885e5c487bfSMatthew G. Knepley   } else {
58862c71b3e2SJacob Faibussowitsch     PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
5887e5c487bfSMatthew G. Knepley     *csize = size;
5888e5c487bfSMatthew G. Knepley   }
5889e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5890e5c487bfSMatthew G. Knepley }
5891e5c487bfSMatthew G. Knepley 
5892552f7358SJed Brown /*@C
5893552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5894552f7358SJed Brown 
5895552f7358SJed Brown   Not collective
5896552f7358SJed Brown 
5897552f7358SJed Brown   Input Parameters:
5898552f7358SJed Brown + dm - The DM
58990298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5900552f7358SJed Brown . v - The local vector
5901eaf898f9SPatrick Sanan . point - The point in the DM
59020298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5903552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5904552f7358SJed Brown 
590522c1ee49SMatthew G. Knepley   Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure()
590622c1ee49SMatthew G. Knepley 
59073813dfbdSMatthew G Knepley   Fortran Notes:
59083813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
59093813dfbdSMatthew G Knepley   include petsc.h90 in your code.
59103813dfbdSMatthew G Knepley 
59113813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
59123813dfbdSMatthew G Knepley 
5913552f7358SJed Brown   Level: intermediate
5914552f7358SJed Brown 
5915552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5916552f7358SJed Brown @*/
59177c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5918a6dfd86eSKarl Rupp {
5919552f7358SJed Brown   PetscInt       size = 0;
5920552f7358SJed Brown 
5921552f7358SJed Brown   PetscFunctionBegin;
5922552f7358SJed Brown   /* Should work without recalculating size */
59239566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values));
5924c9fdaa05SMatthew G. Knepley   *values = NULL;
5925552f7358SJed Brown   PetscFunctionReturn(0);
5926552f7358SJed Brown }
5927552f7358SJed Brown 
59289fbee547SJacob Faibussowitsch static inline void add   (PetscScalar *x, PetscScalar y) {*x += y;}
59299fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5930552f7358SJed Brown 
59319fbee547SJacob 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[])
5932552f7358SJed Brown {
5933552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5934552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5935552f7358SJed Brown   PetscScalar    *a;
5936552f7358SJed Brown   PetscInt        off, cind = 0, k;
5937552f7358SJed Brown 
5938552f7358SJed Brown   PetscFunctionBegin;
59399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
59409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5941552f7358SJed Brown   a    = &array[off];
5942552f7358SJed Brown   if (!cdof || setBC) {
594397e99dd9SToby Isaac     if (clperm) {
594497e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
594597e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5946552f7358SJed Brown     } else {
594797e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
594897e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5949552f7358SJed Brown     }
5950552f7358SJed Brown   } else {
59519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
595297e99dd9SToby Isaac     if (clperm) {
595397e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
5954552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
595597e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
5956552f7358SJed Brown         }
5957552f7358SJed Brown       } else {
5958552f7358SJed Brown         for (k = 0; k < dof; ++k) {
5959552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
596097e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
596197e99dd9SToby Isaac         }
596297e99dd9SToby Isaac       }
596397e99dd9SToby Isaac     } else {
596497e99dd9SToby Isaac       if (perm) {
596597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
596697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
596797e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
596897e99dd9SToby Isaac         }
596997e99dd9SToby Isaac       } else {
597097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
597197e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
597297e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
597397e99dd9SToby Isaac         }
5974552f7358SJed Brown       }
5975552f7358SJed Brown     }
5976552f7358SJed Brown   }
5977552f7358SJed Brown   PetscFunctionReturn(0);
5978552f7358SJed Brown }
5979552f7358SJed Brown 
59809fbee547SJacob 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[])
5981a5e93ea8SMatthew G. Knepley {
5982a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
5983a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5984a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
5985a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
5986a5e93ea8SMatthew G. Knepley 
5987a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
59889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
59899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5990a5e93ea8SMatthew G. Knepley   a    = &array[off];
5991a5e93ea8SMatthew G. Knepley   if (cdof) {
59929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
599397e99dd9SToby Isaac     if (clperm) {
599497e99dd9SToby Isaac       if (perm) {
5995a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
5996a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
599797e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
599897e99dd9SToby Isaac             cind++;
5999a5e93ea8SMatthew G. Knepley           }
6000a5e93ea8SMatthew G. Knepley         }
6001a5e93ea8SMatthew G. Knepley       } else {
6002a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6003a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
600497e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
600597e99dd9SToby Isaac             cind++;
600697e99dd9SToby Isaac           }
600797e99dd9SToby Isaac         }
600897e99dd9SToby Isaac       }
600997e99dd9SToby Isaac     } else {
601097e99dd9SToby Isaac       if (perm) {
601197e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
601297e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
601397e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
601497e99dd9SToby Isaac             cind++;
601597e99dd9SToby Isaac           }
601697e99dd9SToby Isaac         }
601797e99dd9SToby Isaac       } else {
601897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
601997e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
602097e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
602197e99dd9SToby Isaac             cind++;
602297e99dd9SToby Isaac           }
6023a5e93ea8SMatthew G. Knepley         }
6024a5e93ea8SMatthew G. Knepley       }
6025a5e93ea8SMatthew G. Knepley     }
6026a5e93ea8SMatthew G. Knepley   }
6027a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6028a5e93ea8SMatthew G. Knepley }
6029a5e93ea8SMatthew G. Knepley 
60309fbee547SJacob 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[])
6031a6dfd86eSKarl Rupp {
6032552f7358SJed Brown   PetscScalar    *a;
60331a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60341a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
603597e99dd9SToby Isaac   PetscInt        cind = 0, b;
6036552f7358SJed Brown 
6037552f7358SJed Brown   PetscFunctionBegin;
60389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60411a271a75SMatthew G. Knepley   a    = &array[foff];
6042552f7358SJed Brown   if (!fcdof || setBC) {
604397e99dd9SToby Isaac     if (clperm) {
604497e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
604597e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
6046552f7358SJed Brown     } else {
604797e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
604897e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
6049552f7358SJed Brown     }
6050552f7358SJed Brown   } else {
60519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
605297e99dd9SToby Isaac     if (clperm) {
605397e99dd9SToby Isaac       if (perm) {
605497e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
605597e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
605697e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6057552f7358SJed Brown         }
6058552f7358SJed Brown       } else {
605997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
606097e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
606197e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
606297e99dd9SToby Isaac         }
606397e99dd9SToby Isaac       }
606497e99dd9SToby Isaac     } else {
606597e99dd9SToby Isaac       if (perm) {
606697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
606797e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
606897e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
606997e99dd9SToby Isaac         }
607097e99dd9SToby Isaac       } else {
607197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
607297e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
607397e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6074552f7358SJed Brown         }
6075552f7358SJed Brown       }
6076552f7358SJed Brown     }
6077552f7358SJed Brown   }
60781a271a75SMatthew G. Knepley   *offset += fdof;
6079552f7358SJed Brown   PetscFunctionReturn(0);
6080552f7358SJed Brown }
6081552f7358SJed Brown 
60829fbee547SJacob 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[])
6083a5e93ea8SMatthew G. Knepley {
6084a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
60851a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60861a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
60875da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6088ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6089a5e93ea8SMatthew G. Knepley 
6090a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
60919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
60929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60951a271a75SMatthew G. Knepley   a    = &array[foff];
6096a5e93ea8SMatthew G. Knepley   if (fcdof) {
6097ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
60989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
609997e99dd9SToby Isaac     if (clperm) {
610097e99dd9SToby Isaac       if (perm) {
6101ba322698SMatthew G. Knepley         if (comps) {
6102ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6103ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61045da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6105ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6106ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
6107ba322698SMatthew G. Knepley           }
6108ba322698SMatthew G. Knepley         } else {
610997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
611097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
611197e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6112a5e93ea8SMatthew G. Knepley               ++cind;
6113a5e93ea8SMatthew G. Knepley             }
6114a5e93ea8SMatthew G. Knepley           }
6115ba322698SMatthew G. Knepley         }
6116ba322698SMatthew G. Knepley       } else {
6117ba322698SMatthew G. Knepley         if (comps) {
6118ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6119ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61205da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6121ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6122ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
6123ba322698SMatthew G. Knepley           }
6124a5e93ea8SMatthew G. Knepley         } else {
612597e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
612697e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
612797e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
612897e99dd9SToby Isaac               ++cind;
612997e99dd9SToby Isaac             }
613097e99dd9SToby Isaac           }
613197e99dd9SToby Isaac         }
6132ba322698SMatthew G. Knepley       }
613397e99dd9SToby Isaac     } else {
613497e99dd9SToby Isaac       if (perm) {
6135ba322698SMatthew G. Knepley         if (comps) {
6136ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6137ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61385da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6139ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6140ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
6141ba322698SMatthew G. Knepley           }
6142ba322698SMatthew G. Knepley         } else {
614397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
614497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
614597e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
614697e99dd9SToby Isaac               ++cind;
614797e99dd9SToby Isaac             }
614897e99dd9SToby Isaac           }
6149ba322698SMatthew G. Knepley         }
6150ba322698SMatthew G. Knepley       } else {
6151ba322698SMatthew G. Knepley         if (comps) {
6152ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6153ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61545da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6155ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6156ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
6157ba322698SMatthew G. Knepley           }
615897e99dd9SToby Isaac         } else {
615997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
616097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
616197e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6162a5e93ea8SMatthew G. Knepley               ++cind;
6163a5e93ea8SMatthew G. Knepley             }
6164a5e93ea8SMatthew G. Knepley           }
6165a5e93ea8SMatthew G. Knepley         }
6166a5e93ea8SMatthew G. Knepley       }
6167a5e93ea8SMatthew G. Knepley     }
6168ba322698SMatthew G. Knepley   }
61691a271a75SMatthew G. Knepley   *offset += fdof;
6170a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6171a5e93ea8SMatthew G. Knepley }
6172a5e93ea8SMatthew G. Knepley 
61739fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6174a6dfd86eSKarl Rupp {
6175552f7358SJed Brown   PetscScalar    *array;
61761b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
61771b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6178552f7358SJed Brown 
61791b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
61819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
61829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
61839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
61849566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6185b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6186b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
6187b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
6188b6ebb6e6SMatthew G. Knepley 
6189b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
61909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6191b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6192b6ebb6e6SMatthew G. Knepley     {
6193b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6194b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6195b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6196b6ebb6e6SMatthew G. Knepley 
61979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
61989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6199b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
6200b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6201b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6202b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6203b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6204b6ebb6e6SMatthew G. Knepley           }
6205b6ebb6e6SMatthew G. Knepley         } else {
6206b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6207b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6208b6ebb6e6SMatthew G. Knepley           }
6209b6ebb6e6SMatthew G. Knepley         }
6210b6ebb6e6SMatthew G. Knepley       } else {
62119566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6212b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6213b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6214b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6215b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6216b6ebb6e6SMatthew G. Knepley           }
6217b6ebb6e6SMatthew G. Knepley         } else {
6218b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6219b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6220b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6221b6ebb6e6SMatthew G. Knepley           }
6222b6ebb6e6SMatthew G. Knepley         }
6223b6ebb6e6SMatthew G. Knepley       }
6224b6ebb6e6SMatthew G. Knepley     }
6225b6ebb6e6SMatthew G. Knepley   }
62269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6227b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6228b6ebb6e6SMatthew G. Knepley }
62291b406b76SMatthew G. Knepley 
62301b406b76SMatthew G. Knepley /*@C
62311b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62321b406b76SMatthew G. Knepley 
62331b406b76SMatthew G. Knepley   Not collective
62341b406b76SMatthew G. Knepley 
62351b406b76SMatthew G. Knepley   Input Parameters:
62361b406b76SMatthew G. Knepley + dm - The DM
62371b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62381b406b76SMatthew G. Knepley . v - The local vector
6239eaf898f9SPatrick Sanan . point - The point in the DM
62401b406b76SMatthew G. Knepley . values - The array of values
624122c1ee49SMatthew G. Knepley - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES,
624222c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62431b406b76SMatthew G. Knepley 
62441b406b76SMatthew G. Knepley   Fortran Notes:
62451b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62461b406b76SMatthew G. Knepley 
62471b406b76SMatthew G. Knepley   Level: intermediate
62481b406b76SMatthew G. Knepley 
62491b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure()
62501b406b76SMatthew G. Knepley @*/
62511b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
62521b406b76SMatthew G. Knepley {
62531b406b76SMatthew G. Knepley   PetscSection    clSection;
62541b406b76SMatthew G. Knepley   IS              clPoints;
62551b406b76SMatthew G. Knepley   PetscScalar    *array;
62561b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
625727f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6258c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
62591b406b76SMatthew G. Knepley 
62601a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
62611b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62629566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
62631a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
62641a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
62659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
62669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
62671b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
62689566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
62691b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
62701b406b76SMatthew G. Knepley   }
62711a271a75SMatthew G. Knepley   /* Get points */
62729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6273c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6274c459fbc1SJed Brown     PetscInt dof;
62759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
6276c459fbc1SJed Brown     clsize += dof;
6277c459fbc1SJed Brown   }
62789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
62791a271a75SMatthew G. Knepley   /* Get array */
62809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
62811a271a75SMatthew G. Knepley   /* Get values */
6282ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
628397e99dd9SToby Isaac     PetscInt offset = 0, f;
6284552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
628597e99dd9SToby Isaac       const PetscInt    **perms = NULL;
628697e99dd9SToby Isaac       const PetscScalar **flips = NULL;
628797e99dd9SToby Isaac 
62889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6289552f7358SJed Brown       switch (mode) {
6290552f7358SJed Brown       case INSERT_VALUES:
629197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
629297e99dd9SToby Isaac           const PetscInt    point = points[2*p];
629397e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
629497e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
629597e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6296552f7358SJed Brown         } break;
6297552f7358SJed Brown       case INSERT_ALL_VALUES:
629897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
629997e99dd9SToby Isaac           const PetscInt    point = points[2*p];
630097e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
630197e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
630297e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6303552f7358SJed Brown         } break;
6304a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
630597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
630697e99dd9SToby Isaac           const PetscInt    point = points[2*p];
630797e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
630897e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6309ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6310a5e93ea8SMatthew G. Knepley         } break;
6311552f7358SJed Brown       case ADD_VALUES:
631297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
631397e99dd9SToby Isaac           const PetscInt    point = points[2*p];
631497e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
631597e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
631697e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6317552f7358SJed Brown         } break;
6318552f7358SJed Brown       case ADD_ALL_VALUES:
631997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632097e99dd9SToby Isaac           const PetscInt    point = points[2*p];
632197e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
632297e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
632397e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6324552f7358SJed Brown         } break;
6325304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
632697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632797e99dd9SToby Isaac           const PetscInt    point = points[2*p];
632897e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
632997e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6330ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6331304ab55fSMatthew G. Knepley         } break;
6332552f7358SJed Brown       default:
633398921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6334552f7358SJed Brown       }
63359566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
63361a271a75SMatthew G. Knepley     }
6337552f7358SJed Brown   } else {
63381a271a75SMatthew G. Knepley     PetscInt dof, off;
633997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
634097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63411a271a75SMatthew G. Knepley 
63429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
6343552f7358SJed Brown     switch (mode) {
6344552f7358SJed Brown     case INSERT_VALUES:
634597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
634697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
634797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
634897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63499566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
635097e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
6351552f7358SJed Brown       } break;
6352552f7358SJed Brown     case INSERT_ALL_VALUES:
635397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
635497e99dd9SToby Isaac         const PetscInt    point = points[2*p];
635597e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
635697e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
635897e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6359552f7358SJed Brown       } break;
6360a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
636197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
636297e99dd9SToby Isaac         const PetscInt    point = points[2*p];
636397e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
636497e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63659566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
636697e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6367a5e93ea8SMatthew G. Knepley       } break;
6368552f7358SJed Brown     case ADD_VALUES:
636997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
637097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
637197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
637297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
637497e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6375552f7358SJed Brown       } break;
6376552f7358SJed Brown     case ADD_ALL_VALUES:
637797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
637897e99dd9SToby Isaac         const PetscInt    point = points[2*p];
637997e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638097e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63819566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
638297e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6383552f7358SJed Brown       } break;
6384304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
638597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
639097e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6391304ab55fSMatthew G. Knepley       } break;
6392552f7358SJed Brown     default:
639398921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6394552f7358SJed Brown     }
63959566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
6396552f7358SJed Brown   }
63971a271a75SMatthew G. Knepley   /* Cleanup points */
63989566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
63991a271a75SMatthew G. Knepley   /* Cleanup array */
64009566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6401552f7358SJed Brown   PetscFunctionReturn(0);
6402552f7358SJed Brown }
6403552f7358SJed Brown 
64045f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
64059fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
64065f790a90SMatthew G. Knepley {
64075f790a90SMatthew G. Knepley   PetscFunctionBegin;
64085f790a90SMatthew G. Knepley   if (label) {
64095f790a90SMatthew G. Knepley     PetscInt       val, fdof;
64105f790a90SMatthew G. Knepley 
64115f790a90SMatthew G. Knepley     /* There is a problem with this:
64125f790a90SMatthew G. Knepley          Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that
64135f790a90SMatthew G. Knepley        touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell.
64145f790a90SMatthew G. Knepley        Thus I am only going to check val != -1, not val != labelId
64155f790a90SMatthew G. Knepley     */
64169566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, point, &val));
64175f790a90SMatthew G. Knepley     if (val < 0) {
64189566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64195f790a90SMatthew G. Knepley       *offset += fdof;
64205f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
64215f790a90SMatthew G. Knepley     }
64225f790a90SMatthew G. Knepley   }
64235f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64245f790a90SMatthew G. Knepley }
64255f790a90SMatthew G. Knepley 
642697529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64275f790a90SMatthew G. Knepley PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode)
6428e07394fbSMatthew G. Knepley {
6429e07394fbSMatthew G. Knepley   PetscSection    clSection;
6430e07394fbSMatthew G. Knepley   IS              clPoints;
6431e07394fbSMatthew G. Knepley   PetscScalar    *array;
6432e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
643397529cf3SJed Brown   const PetscInt *clp;
6434e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
643597e99dd9SToby Isaac   PetscInt        offset = 0, f;
6436e07394fbSMatthew G. Knepley 
6437e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6438e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64399566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6440e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6441e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6443e07394fbSMatthew G. Knepley   /* Get points */
64449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6445e07394fbSMatthew G. Knepley   /* Get array */
64469566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6447e07394fbSMatthew G. Knepley   /* Get values */
6448e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
644997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
645097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
645197e99dd9SToby Isaac 
6452e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6453e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6454e07394fbSMatthew G. Knepley         PetscInt fdof;
64559566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6456e07394fbSMatthew G. Knepley         offset += fdof;
6457e07394fbSMatthew G. Knepley       }
6458e07394fbSMatthew G. Knepley       continue;
6459e07394fbSMatthew G. Knepley     }
64609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6461e07394fbSMatthew G. Knepley     switch (mode) {
6462e07394fbSMatthew G. Knepley     case INSERT_VALUES:
646397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
646497e99dd9SToby Isaac         const PetscInt    point = points[2*p];
646597e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
646697e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64675f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64689566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
6469e07394fbSMatthew G. Knepley       } break;
6470e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
647197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
647297e99dd9SToby Isaac         const PetscInt    point = points[2*p];
647397e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
647497e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64755f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64769566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
6477e07394fbSMatthew G. Knepley       } break;
6478e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
647997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
648097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
648197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
648297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64835f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64849566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
6485e07394fbSMatthew G. Knepley       } break;
6486e07394fbSMatthew G. Knepley     case ADD_VALUES:
648797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
648897e99dd9SToby Isaac         const PetscInt    point = points[2*p];
648997e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649097e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64915f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64929566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
6493e07394fbSMatthew G. Knepley       } break;
6494e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
649597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
649797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64995f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65009566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
6501e07394fbSMatthew G. Knepley       } break;
6502e07394fbSMatthew G. Knepley     default:
650398921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6504e07394fbSMatthew G. Knepley     }
65059566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6506e07394fbSMatthew G. Knepley   }
6507e07394fbSMatthew G. Knepley   /* Cleanup points */
65089566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6509e07394fbSMatthew G. Knepley   /* Cleanup array */
65109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6511e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6512e07394fbSMatthew G. Knepley }
6513e07394fbSMatthew G. Knepley 
65147cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6515552f7358SJed Brown {
6516552f7358SJed Brown   PetscMPIInt    rank;
6517552f7358SJed Brown   PetscInt       i, j;
6518552f7358SJed Brown 
6519552f7358SJed Brown   PetscFunctionBegin;
65209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
65219566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point));
65229566063dSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]));
65239566063dSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]));
6524b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6525557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6526b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
65279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6528b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6529519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j])));
6531552f7358SJed Brown #else
65329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]));
6533552f7358SJed Brown #endif
6534552f7358SJed Brown     }
65359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6536552f7358SJed Brown   }
6537552f7358SJed Brown   PetscFunctionReturn(0);
6538552f7358SJed Brown }
6539552f7358SJed Brown 
654005586334SMatthew G. Knepley /*
654105586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
654205586334SMatthew G. Knepley 
654305586334SMatthew G. Knepley   Input Parameters:
654405586334SMatthew G. Knepley + section - The section for this data layout
654536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
654605586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
654705586334SMatthew G. Knepley . off     - The global offset of this point
654805586334SMatthew G. Knepley . loff    - The local offset of each field
6549a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
655005586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
655105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
655205586334SMatthew G. Knepley 
655305586334SMatthew G. Knepley   Output Parameter:
655405586334SMatthew G. Knepley . indices - Indices for dofs on this point
655505586334SMatthew G. Knepley 
655605586334SMatthew G. Knepley   Level: developer
655705586334SMatthew G. Knepley 
655805586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
655905586334SMatthew G. Knepley */
656036fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6561a6dfd86eSKarl Rupp {
6562e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6563552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6564552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6565552f7358SJed Brown   PetscInt        cind = 0, k;
6566552f7358SJed Brown 
6567552f7358SJed Brown   PetscFunctionBegin;
65682c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
65699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
65709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6571552f7358SJed Brown   if (!cdof || setBC) {
657205586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
657305586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
657405586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
657505586334SMatthew G. Knepley 
657605586334SMatthew G. Knepley       indices[ind] = off + k;
6577552f7358SJed Brown     }
6578552f7358SJed Brown   } else {
65799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
65804acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
658105586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
658205586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
658305586334SMatthew G. Knepley 
65844acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
65854acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
658605586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
65874acb8e1eSToby Isaac         ++cind;
65884acb8e1eSToby Isaac       } else {
658936fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6590552f7358SJed Brown       }
6591552f7358SJed Brown     }
6592552f7358SJed Brown   }
6593e6ccafaeSMatthew G Knepley   *loff += dof;
6594552f7358SJed Brown   PetscFunctionReturn(0);
6595552f7358SJed Brown }
6596552f7358SJed Brown 
65977e29afd2SMatthew G. Knepley /*
659836fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
65997e29afd2SMatthew G. Knepley 
660036fa2b79SJed Brown  Input Parameters:
660136fa2b79SJed Brown + section - a section (global or local)
660236fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
660336fa2b79SJed Brown . point - point within section
660436fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
660536fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
660636fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
660736fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
660836fa2b79SJed Brown . permsoff - offset
660936fa2b79SJed Brown - indperm - index permutation
661036fa2b79SJed Brown 
661136fa2b79SJed Brown  Output Parameter:
661236fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
661336fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
661436fa2b79SJed Brown 
661536fa2b79SJed Brown  Notes:
661636fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
661736fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
661836fa2b79SJed Brown  in the local vector.
661936fa2b79SJed Brown 
662036fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
662136fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
662236fa2b79SJed Brown 
662336fa2b79SJed Brown  Developer Note:
662436fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
662536fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
662636fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
662736fa2b79SJed Brown 
662836fa2b79SJed Brown  Example:
662936fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
663036fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
663136fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
663236fa2b79SJed 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.
663336fa2b79SJed Brown 
663436fa2b79SJed Brown  Level: developer
66357e29afd2SMatthew G. Knepley */
663636fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
6637a6dfd86eSKarl Rupp {
6638552f7358SJed Brown   PetscInt       numFields, foff, f;
6639552f7358SJed Brown 
6640552f7358SJed Brown   PetscFunctionBegin;
66412c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
66429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6643552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66444acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6645552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66464acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66474acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6648552f7358SJed Brown 
66499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
66509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
6651552f7358SJed Brown     if (!cfdof || setBC) {
665205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
665305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
665405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
665505586334SMatthew G. Knepley 
665605586334SMatthew G. Knepley         indices[ind] = off+foff+b;
665705586334SMatthew G. Knepley       }
6658552f7358SJed Brown     } else {
66599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
666005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
666105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
666205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
666305586334SMatthew G. Knepley 
66644acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
666505586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6666552f7358SJed Brown           ++cind;
6667552f7358SJed Brown         } else {
666836fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6669552f7358SJed Brown         }
6670552f7358SJed Brown       }
6671552f7358SJed Brown     }
667236fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6673552f7358SJed Brown     foffs[f] += fdof;
6674552f7358SJed Brown   }
6675552f7358SJed Brown   PetscFunctionReturn(0);
6676552f7358SJed Brown }
6677552f7358SJed Brown 
66787e29afd2SMatthew G. Knepley /*
66797e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
66807e29afd2SMatthew G. Knepley 
66817e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6682645102dcSJed Brown 
6683645102dcSJed Brown  Notes:
6684645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6685645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
66867e29afd2SMatthew G. Knepley */
6687645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
66887e29afd2SMatthew G. Knepley {
66897e29afd2SMatthew G. Knepley   PetscInt       numFields, foff, f;
66907e29afd2SMatthew G. Knepley 
66917e29afd2SMatthew G. Knepley   PetscFunctionBegin;
66929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
66937e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
66947e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
66957e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66967e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
66977e29afd2SMatthew G. Knepley     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
66987e29afd2SMatthew G. Knepley 
66999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
67019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
6702645102dcSJed Brown     if (!cfdof) {
670305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
670405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
670505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
670605586334SMatthew G. Knepley 
670705586334SMatthew G. Knepley         indices[ind] = foff+b;
670805586334SMatthew G. Knepley       }
67097e29afd2SMatthew G. Knepley     } else {
67109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
671105586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
671205586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
671305586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
671405586334SMatthew G. Knepley 
67157e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
671605586334SMatthew G. Knepley           indices[ind] = -(foff+b+1);
67177e29afd2SMatthew G. Knepley           ++cind;
67187e29afd2SMatthew G. Knepley         } else {
671905586334SMatthew G. Knepley           indices[ind] = foff+b-cind;
67207e29afd2SMatthew G. Knepley         }
67217e29afd2SMatthew G. Knepley       }
67227e29afd2SMatthew G. Knepley     }
67237e29afd2SMatthew G. Knepley     foffs[f] += fdof;
67247e29afd2SMatthew G. Knepley   }
67257e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
67267e29afd2SMatthew G. Knepley }
67277e29afd2SMatthew G. Knepley 
67284acb8e1eSToby Isaac PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft)
6729d3d1a6afSToby Isaac {
6730d3d1a6afSToby Isaac   Mat             cMat;
6731d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6732d3d1a6afSToby Isaac   IS              aIS;
6733d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6734d3d1a6afSToby Isaac   const PetscInt  *anchors;
6735e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6736d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6737d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6738d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6739d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6740d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6741d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6742d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
67436ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6744d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6745d3d1a6afSToby Isaac 
6746d3d1a6afSToby Isaac   PetscFunctionBegin;
6747d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6748d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
67499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6750d3d1a6afSToby Isaac 
67519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
6752d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6753d3d1a6afSToby Isaac   if (aSec) {
67549566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
67559566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS,&anchors));
67569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd));
6757d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6758d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6759d3d1a6afSToby Isaac      * into the global matrix anyway) */
6760d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6761d3d1a6afSToby Isaac       PetscInt b    = points[p];
67624b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6763d3d1a6afSToby Isaac 
67649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
67654b2f2278SToby Isaac       if (!bSecDof) {
67664b2f2278SToby Isaac         continue;
67674b2f2278SToby Isaac       }
6768d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
67699566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,b,&bDof));
6770d3d1a6afSToby Isaac       }
6771d3d1a6afSToby Isaac       if (bDof) {
6772d3d1a6afSToby Isaac         /* this point is constrained */
6773d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6774d3d1a6afSToby Isaac         PetscInt bOff, q;
6775d3d1a6afSToby Isaac 
6776d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6777d3d1a6afSToby Isaac         newNumPoints  += bDof;
67789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,b,&bOff));
6779d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6780d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6781d3d1a6afSToby Isaac           PetscInt aDof;
6782d3d1a6afSToby Isaac 
67839566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
6784d3d1a6afSToby Isaac           newNumIndices += aDof;
6785d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6786d3d1a6afSToby Isaac             PetscInt fDof;
6787d3d1a6afSToby Isaac 
67889566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
6789d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6790d3d1a6afSToby Isaac           }
6791d3d1a6afSToby Isaac         }
6792d3d1a6afSToby Isaac       }
6793d3d1a6afSToby Isaac       else {
6794d3d1a6afSToby Isaac         /* this point is not constrained */
6795d3d1a6afSToby Isaac         newNumPoints++;
67964b2f2278SToby Isaac         newNumIndices += bSecDof;
6797d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6798d3d1a6afSToby Isaac           PetscInt fDof;
6799d3d1a6afSToby Isaac 
68009566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6801d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6802d3d1a6afSToby Isaac         }
6803d3d1a6afSToby Isaac       }
6804d3d1a6afSToby Isaac     }
6805d3d1a6afSToby Isaac   }
6806d3d1a6afSToby Isaac   if (!anyConstrained) {
680772b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
680872b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
680972b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
681072b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
68119566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
6812d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6813d3d1a6afSToby Isaac   }
6814d3d1a6afSToby Isaac 
68156ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
68166ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68176ecaa68aSToby Isaac 
6818f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6819d3d1a6afSToby Isaac 
68206ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68216ecaa68aSToby Isaac     if (offsets) {
68226ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
68236ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
68246ecaa68aSToby Isaac       }
68256ecaa68aSToby Isaac     }
68269566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
68276ecaa68aSToby Isaac     PetscFunctionReturn(0);
68286ecaa68aSToby Isaac   }
68296ecaa68aSToby Isaac 
68302c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices);
6831d3d1a6afSToby Isaac 
68329566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
6833d3d1a6afSToby Isaac 
6834d3d1a6afSToby Isaac   /* workspaces */
6835d3d1a6afSToby Isaac   if (numFields) {
6836d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
68379566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
68389566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
6839d3d1a6afSToby Isaac     }
6840d3d1a6afSToby Isaac   }
6841d3d1a6afSToby Isaac   else {
68429566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
68439566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]));
6844d3d1a6afSToby Isaac   }
6845d3d1a6afSToby Isaac 
6846d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6847d3d1a6afSToby Isaac   if (numFields) {
68484b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68494b2f2278SToby Isaac 
6850d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6851d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
68524b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6853d3d1a6afSToby Isaac 
68549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
68554b2f2278SToby Isaac       if (!bSecDof) {
68564b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
68574b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
68584b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
68594b2f2278SToby Isaac         }
68604b2f2278SToby Isaac         continue;
68614b2f2278SToby Isaac       }
6862d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
68639566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6864d3d1a6afSToby Isaac       }
6865d3d1a6afSToby Isaac       if (bDof) {
6866d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6867d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6868d3d1a6afSToby Isaac 
68699566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
68709566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6871d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6872d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6873d3d1a6afSToby Isaac             PetscInt aFDof;
6874d3d1a6afSToby Isaac 
68759566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
6876d3d1a6afSToby Isaac             allFDof += aFDof;
6877d3d1a6afSToby Isaac           }
6878d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6879d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6880d3d1a6afSToby Isaac         }
6881d3d1a6afSToby Isaac       }
6882d3d1a6afSToby Isaac       else {
6883d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6884d3d1a6afSToby Isaac           PetscInt fDof;
6885d3d1a6afSToby Isaac 
68869566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6887d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6888d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6889d3d1a6afSToby Isaac         }
6890d3d1a6afSToby Isaac       }
6891d3d1a6afSToby Isaac     }
68924b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
68934b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
68944b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6895d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6896d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6897d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6898d3d1a6afSToby Isaac       }
689919f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
690019f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
69019566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
6902d3d1a6afSToby Isaac     }
6903d3d1a6afSToby Isaac   }
6904d3d1a6afSToby Isaac   else {
6905d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6906d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
69074b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6908d3d1a6afSToby Isaac 
69099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
69104b2f2278SToby Isaac       if (!bSecDof) {
69114b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69124b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69134b2f2278SToby Isaac         continue;
69144b2f2278SToby Isaac       }
6915d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6917d3d1a6afSToby Isaac       }
6918d3d1a6afSToby Isaac       if (bDof) {
69194b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6920d3d1a6afSToby Isaac 
69219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6922d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6923d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6924d3d1a6afSToby Isaac 
69259566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
6926d3d1a6afSToby Isaac           allDof += aDof;
6927d3d1a6afSToby Isaac         }
6928d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
69294b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6930d3d1a6afSToby Isaac       }
6931d3d1a6afSToby Isaac       else {
69324b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6933d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6934d3d1a6afSToby Isaac       }
6935d3d1a6afSToby Isaac     }
6936d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6937d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6938d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6939d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6940d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6941d3d1a6afSToby Isaac     }
69429566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
6943d3d1a6afSToby Isaac   }
6944d3d1a6afSToby Isaac 
69456ecaa68aSToby Isaac   /* output arrays */
69469566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
69476ecaa68aSToby Isaac 
6948d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
69499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
69509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
69519566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices));
69529566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
6953d3d1a6afSToby Isaac   if (numFields) {
6954d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6955d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6956d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
69574b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6958d3d1a6afSToby Isaac 
69599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
69604b2f2278SToby Isaac       if (!bSecDof) {
69614b2f2278SToby Isaac         continue;
69624b2f2278SToby Isaac       }
6963d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69649566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6965d3d1a6afSToby Isaac       }
6966d3d1a6afSToby Isaac       if (bDof) {
6967d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6968d3d1a6afSToby Isaac 
6969d3d1a6afSToby Isaac         fStart[0] = 0;
6970d3d1a6afSToby Isaac         fEnd[0]   = 0;
6971d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6972d3d1a6afSToby Isaac           PetscInt fDof;
6973d3d1a6afSToby Isaac 
69749566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
6975d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
6976d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
6977d3d1a6afSToby Isaac         }
69789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
69799566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
6980d3d1a6afSToby Isaac 
6981d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
6982d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
6983d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6984d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
6985d3d1a6afSToby Isaac 
6986d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
6987d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
6988d3d1a6afSToby Isaac         }
69899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6990d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6991d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
6992d3d1a6afSToby Isaac 
6993d3d1a6afSToby 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 */
6994d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
6995d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
69969566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
69979566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
6998d3d1a6afSToby Isaac         }
6999d3d1a6afSToby Isaac         newP += bDof;
7000d3d1a6afSToby Isaac 
70016ecaa68aSToby Isaac         if (outValues) {
7002d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
7003d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
70049566063dSJacob Faibussowitsch             PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]));
7005d3d1a6afSToby Isaac           }
7006d3d1a6afSToby Isaac         }
70076ecaa68aSToby Isaac       }
7008d3d1a6afSToby Isaac       else {
7009d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7010d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7011d3d1a6afSToby Isaac         newP++;
7012d3d1a6afSToby Isaac       }
7013d3d1a6afSToby Isaac     }
7014d3d1a6afSToby Isaac   } else {
7015d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7016d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
7017d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70184b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7019d3d1a6afSToby Isaac 
70209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
70214b2f2278SToby Isaac       if (!bSecDof) {
70224b2f2278SToby Isaac         continue;
70234b2f2278SToby Isaac       }
7024d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
70259566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7026d3d1a6afSToby Isaac       }
7027d3d1a6afSToby Isaac       if (bDof) {
7028d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7029d3d1a6afSToby Isaac 
70309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70319566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7032d3d1a6afSToby Isaac 
70339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset (aSec, b, &bOff));
7034d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7035d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7036d3d1a6afSToby Isaac 
7037d3d1a6afSToby 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 */
7038d3d1a6afSToby Isaac 
7039d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7040d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70419566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70429566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7043d3d1a6afSToby Isaac         }
7044d3d1a6afSToby Isaac         newP += bDof;
7045d3d1a6afSToby Isaac 
7046d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
70476ecaa68aSToby Isaac         if (outValues) {
70489566063dSJacob Faibussowitsch           PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]));
7049d3d1a6afSToby Isaac         }
70506ecaa68aSToby Isaac       }
7051d3d1a6afSToby Isaac       else {
7052d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7053d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7054d3d1a6afSToby Isaac         newP++;
7055d3d1a6afSToby Isaac       }
7056d3d1a6afSToby Isaac     }
7057d3d1a6afSToby Isaac   }
7058d3d1a6afSToby Isaac 
70596ecaa68aSToby Isaac   if (outValues) {
70609566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
70619566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices));
7062d3d1a6afSToby Isaac     /* multiply constraints on the right */
7063d3d1a6afSToby Isaac     if (numFields) {
7064d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7065d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7066d3d1a6afSToby Isaac 
7067d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7068d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7069d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7070d3d1a6afSToby Isaac           PetscInt c, r, k;
7071d3d1a6afSToby Isaac           PetscInt dof;
7072d3d1a6afSToby Isaac 
70739566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
70744b2f2278SToby Isaac           if (!dof) {
70754b2f2278SToby Isaac             continue;
70764b2f2278SToby Isaac           }
7077d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7078d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
7079d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
7080d3d1a6afSToby Isaac 
7081d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7082d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7083d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
70844acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7085d3d1a6afSToby Isaac                 }
7086d3d1a6afSToby Isaac               }
7087d3d1a6afSToby Isaac             }
7088d3d1a6afSToby Isaac           }
7089d3d1a6afSToby Isaac           else {
7090d3d1a6afSToby Isaac             /* copy this column as is */
7091d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7092d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
7093d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7094d3d1a6afSToby Isaac               }
7095d3d1a6afSToby Isaac             }
7096d3d1a6afSToby Isaac           }
7097d3d1a6afSToby Isaac           oldOff += dof;
7098d3d1a6afSToby Isaac         }
7099d3d1a6afSToby Isaac       }
7100d3d1a6afSToby Isaac     }
7101d3d1a6afSToby Isaac     else {
7102d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7103d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7104d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7105d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7106d3d1a6afSToby Isaac         PetscInt c, r, k;
7107d3d1a6afSToby Isaac         PetscInt dof;
7108d3d1a6afSToby Isaac 
71099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,b,&dof));
71104b2f2278SToby Isaac         if (!dof) {
71114b2f2278SToby Isaac           continue;
71124b2f2278SToby Isaac         }
7113d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7114d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
7115d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
7116d3d1a6afSToby Isaac 
7117d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7118d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7119d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
7120d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7121d3d1a6afSToby Isaac               }
7122d3d1a6afSToby Isaac             }
7123d3d1a6afSToby Isaac           }
7124d3d1a6afSToby Isaac         }
7125d3d1a6afSToby Isaac         else {
7126d3d1a6afSToby Isaac           /* copy this column as is */
7127d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7128d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
7129d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7130d3d1a6afSToby Isaac             }
7131d3d1a6afSToby Isaac           }
7132d3d1a6afSToby Isaac         }
7133d3d1a6afSToby Isaac         oldOff += dof;
7134d3d1a6afSToby Isaac       }
7135d3d1a6afSToby Isaac     }
7136d3d1a6afSToby Isaac 
71376ecaa68aSToby Isaac     if (multiplyLeft) {
71389566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues));
71399566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices));
7140d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7141d3d1a6afSToby Isaac       if (numFields) {
7142d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7143d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7144d3d1a6afSToby Isaac 
7145d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7146d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7147d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7148d3d1a6afSToby Isaac             PetscInt c, r, k;
7149d3d1a6afSToby Isaac             PetscInt dof;
7150d3d1a6afSToby Isaac 
71519566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
7152d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7153d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
7154d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
7155d3d1a6afSToby Isaac 
7156d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7157d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7158d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
7159d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7160d3d1a6afSToby Isaac                   }
7161d3d1a6afSToby Isaac                 }
7162d3d1a6afSToby Isaac               }
7163d3d1a6afSToby Isaac             }
7164d3d1a6afSToby Isaac             else {
7165d3d1a6afSToby Isaac               /* copy this row as is */
7166d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7167d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7168d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7169d3d1a6afSToby Isaac                 }
7170d3d1a6afSToby Isaac               }
7171d3d1a6afSToby Isaac             }
7172d3d1a6afSToby Isaac             oldOff += dof;
7173d3d1a6afSToby Isaac           }
7174d3d1a6afSToby Isaac         }
7175d3d1a6afSToby Isaac       }
7176d3d1a6afSToby Isaac       else {
7177d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7178d3d1a6afSToby Isaac 
7179d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7180d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7181d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7182d3d1a6afSToby Isaac           PetscInt c, r, k;
7183d3d1a6afSToby Isaac           PetscInt dof;
7184d3d1a6afSToby Isaac 
71859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,b,&dof));
7186d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7187d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
7188d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
7189d3d1a6afSToby Isaac 
7190d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7191d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7192d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
7193d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7194d3d1a6afSToby Isaac                 }
7195d3d1a6afSToby Isaac               }
7196d3d1a6afSToby Isaac             }
7197d3d1a6afSToby Isaac           }
7198d3d1a6afSToby Isaac           else {
7199d3d1a6afSToby Isaac             /* copy this row as is */
72009fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7201d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7202d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7203d3d1a6afSToby Isaac               }
7204d3d1a6afSToby Isaac             }
7205d3d1a6afSToby Isaac           }
7206d3d1a6afSToby Isaac           oldOff += dof;
7207d3d1a6afSToby Isaac         }
7208d3d1a6afSToby Isaac       }
7209d3d1a6afSToby Isaac 
72109566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
72116ecaa68aSToby Isaac     }
72126ecaa68aSToby Isaac     else {
72136ecaa68aSToby Isaac       newValues = tmpValues;
72146ecaa68aSToby Isaac     }
72156ecaa68aSToby Isaac   }
72166ecaa68aSToby Isaac 
7217d3d1a6afSToby Isaac   /* clean up */
72189566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices));
72199566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
72206ecaa68aSToby Isaac 
7221d3d1a6afSToby Isaac   if (numFields) {
7222d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72239566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
72249566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
72259566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
7226d3d1a6afSToby Isaac     }
7227d3d1a6afSToby Isaac   }
7228d3d1a6afSToby Isaac   else {
72299566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
72309566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
72319566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]));
7232d3d1a6afSToby Isaac   }
72339566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
7234d3d1a6afSToby Isaac 
7235d3d1a6afSToby Isaac   /* output */
72366ecaa68aSToby Isaac   if (outPoints) {
7237d3d1a6afSToby Isaac     *outPoints = newPoints;
72386ecaa68aSToby Isaac   }
72396ecaa68aSToby Isaac   else {
72409566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
72416ecaa68aSToby Isaac   }
724231620726SToby Isaac   if (outValues) {
7243d3d1a6afSToby Isaac     *outValues = newValues;
72446ecaa68aSToby Isaac   }
72456ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7246d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7247d3d1a6afSToby Isaac   }
7248d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7249d3d1a6afSToby Isaac }
7250d3d1a6afSToby Isaac 
72514a1e0b3eSMatthew G. Knepley /*@C
725271f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72537cd05799SMatthew G. Knepley 
72547cd05799SMatthew G. Knepley   Not collective
72557cd05799SMatthew G. Knepley 
72567cd05799SMatthew G. Knepley   Input Parameters:
72577cd05799SMatthew G. Knepley + dm         - The DM
725871f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
725971f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
726071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
726171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
72627cd05799SMatthew G. Knepley 
726371f0bbf9SMatthew G. Knepley   Output Parameters:
726471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
726571f0bbf9SMatthew G. Knepley . indices    - The dof indices
726671f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
726771f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
72687cd05799SMatthew G. Knepley 
726936fa2b79SJed Brown   Notes:
727036fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
727136fa2b79SJed Brown 
727236fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
727336fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
727436fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
727536fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
727636fa2b79SJed Brown   indices (with the above semantics) are implied.
72777cd05799SMatthew G. Knepley 
72787cd05799SMatthew G. Knepley   Level: advanced
72797cd05799SMatthew G. Knepley 
728036fa2b79SJed Brown .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
72814a1e0b3eSMatthew G. Knepley @*/
728271f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
728371f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
72847773e69fSMatthew G. Knepley {
728571f0bbf9SMatthew G. Knepley   /* Closure ordering */
72867773e69fSMatthew G. Knepley   PetscSection        clSection;
72877773e69fSMatthew G. Knepley   IS                  clPoints;
728871f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
728971f0bbf9SMatthew G. Knepley   PetscInt           *points;
729071f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
729171f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
72924acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
729371f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
729471f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
729571f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
729671f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
729771f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
729871f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
729971f0bbf9SMatthew G. Knepley 
730071f0bbf9SMatthew G. Knepley   PetscInt           *idx;
730171f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
730271f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
73037773e69fSMatthew G. Knepley 
730471f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
73057773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73067773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
730736fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7308dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
730971f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
7310dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
731171f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
73129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
73132c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf);
73149566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
731571f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
73169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7317c459fbc1SJed Brown   if (useClPerm) {
7318c459fbc1SJed Brown     PetscInt depth, clsize;
73199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7320c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7321c459fbc1SJed Brown       PetscInt dof;
73229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
7323c459fbc1SJed Brown       clsize += dof;
7324c459fbc1SJed Brown     }
73259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
7326c459fbc1SJed Brown   }
732771f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
732871f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
73297773e69fSMatthew G. Knepley     PetscInt dof, fdof;
73307773e69fSMatthew G. Knepley 
73319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
73327773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
73339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
73347773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
73357773e69fSMatthew G. Knepley     }
733671f0bbf9SMatthew G. Knepley     Ni += dof;
73377773e69fSMatthew G. Knepley   }
73387773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
73392c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni);
734071f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
734171f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73429566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73439566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
734471f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
734571f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
734671f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73476ecaa68aSToby Isaac 
734871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
734971f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
735071f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
735171f0bbf9SMatthew G. Knepley 
73529566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
73539566063dSJacob Faibussowitsch         else     PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
735471f0bbf9SMatthew G. Knepley         if (flip) {
735571f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
735671f0bbf9SMatthew G. Knepley 
735771f0bbf9SMatthew G. Knepley           if (!valCopy) {
73589566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
735971f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
736071f0bbf9SMatthew G. Knepley             *values = valCopy;
736171f0bbf9SMatthew G. Knepley           }
736271f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
736371f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
736471f0bbf9SMatthew G. Knepley 
736571f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
736671f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
736771f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
73686ecaa68aSToby Isaac             }
73696ecaa68aSToby Isaac           }
737071f0bbf9SMatthew G. Knepley         }
737171f0bbf9SMatthew G. Knepley         foffset += fdof;
737271f0bbf9SMatthew G. Knepley       }
737371f0bbf9SMatthew G. Knepley     }
737471f0bbf9SMatthew G. Knepley   }
737571f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
73769566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
737771f0bbf9SMatthew G. Knepley   if (NclC) {
73789566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
737971f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
73809566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73819566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
738271f0bbf9SMatthew G. Knepley     }
738371f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
73849566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
73859566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
738671f0bbf9SMatthew G. Knepley     }
73879566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
738871f0bbf9SMatthew G. Knepley     Ncl     = NclC;
738971f0bbf9SMatthew G. Knepley     Ni      = NiC;
739071f0bbf9SMatthew G. Knepley     points  = pointsC;
739171f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
739271f0bbf9SMatthew G. Knepley   }
739371f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
73949566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
739571f0bbf9SMatthew G. Knepley   if (Nf) {
739671f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
739771f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
739871f0bbf9SMatthew G. Knepley 
739971f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
74009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
740171f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
740271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
740371f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
740471f0bbf9SMatthew G. Knepley 
74059566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
74067773e69fSMatthew G. Knepley       }
74077773e69fSMatthew G. Knepley     } else {
740871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
740971f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
741071f0bbf9SMatthew G. Knepley 
74119566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
741271f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
741371f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
741471f0bbf9SMatthew G. Knepley          * global section. */
74159566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
741671f0bbf9SMatthew G. Knepley       }
741771f0bbf9SMatthew G. Knepley     }
741871f0bbf9SMatthew G. Knepley   } else {
741971f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
742071f0bbf9SMatthew G. Knepley 
742171f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
742271f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
74234acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
74244acb8e1eSToby Isaac 
74259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
742671f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
742771f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
74289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
74297773e69fSMatthew G. Knepley     }
74307773e69fSMatthew G. Knepley   }
743171f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
743271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
74339566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74349566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
74354acb8e1eSToby Isaac   }
743671f0bbf9SMatthew G. Knepley   if (NclC) {
74379566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC));
74387773e69fSMatthew G. Knepley   } else {
74399566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
74407773e69fSMatthew G. Knepley   }
744171f0bbf9SMatthew G. Knepley 
744271f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
744371f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
74447773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74457773e69fSMatthew G. Knepley }
74467773e69fSMatthew G. Knepley 
74477cd05799SMatthew G. Knepley /*@C
744871f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74497cd05799SMatthew G. Knepley 
74507cd05799SMatthew G. Knepley   Not collective
74517cd05799SMatthew G. Knepley 
74527cd05799SMatthew G. Knepley   Input Parameters:
74537cd05799SMatthew G. Knepley + dm         - The DM
745471f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
745571f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
745671f0bbf9SMatthew G. Knepley . point      - The point defining the closure
745771f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
745871f0bbf9SMatthew G. Knepley 
745971f0bbf9SMatthew G. Knepley   Output Parameters:
746071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
746171f0bbf9SMatthew G. Knepley . indices    - The dof indices
746271f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
746371f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
746471f0bbf9SMatthew G. Knepley 
746571f0bbf9SMatthew G. Knepley   Notes:
746671f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
746771f0bbf9SMatthew G. Knepley 
746871f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
746971f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
747071f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
747171f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
747271f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
74737cd05799SMatthew G. Knepley 
74747cd05799SMatthew G. Knepley   Level: advanced
74757cd05799SMatthew G. Knepley 
747671f0bbf9SMatthew G. Knepley .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
74777cd05799SMatthew G. Knepley @*/
747871f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
747971f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
74807773e69fSMatthew G. Knepley {
74817773e69fSMatthew G. Knepley   PetscFunctionBegin;
74827773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7483064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
74849566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
74857773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74867773e69fSMatthew G. Knepley }
74877773e69fSMatthew G. Knepley 
74887f5d1fdeSMatthew G. Knepley /*@C
74897f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
74907f5d1fdeSMatthew G. Knepley 
74917f5d1fdeSMatthew G. Knepley   Not collective
74927f5d1fdeSMatthew G. Knepley 
74937f5d1fdeSMatthew G. Knepley   Input Parameters:
74947f5d1fdeSMatthew G. Knepley + dm - The DM
7495ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7496ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
74977f5d1fdeSMatthew G. Knepley . A - The matrix
7498eaf898f9SPatrick Sanan . point - The point in the DM
74997f5d1fdeSMatthew G. Knepley . values - The array of values
75007f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75017f5d1fdeSMatthew G. Knepley 
75027f5d1fdeSMatthew G. Knepley   Fortran Notes:
75037f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
75047f5d1fdeSMatthew G. Knepley 
75057f5d1fdeSMatthew G. Knepley   Level: intermediate
75067f5d1fdeSMatthew G. Knepley 
75074a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
75087f5d1fdeSMatthew G. Knepley @*/
75097c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7510552f7358SJed Brown {
7511552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7512552f7358SJed Brown   PetscInt          *indices;
751371f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
751471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7515552f7358SJed Brown   PetscErrorCode     ierr;
7516552f7358SJed Brown 
7517552f7358SJed Brown   PetscFunctionBegin;
7518552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
75199566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
75203dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75219566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
75223dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
75233dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7524552f7358SJed Brown 
75259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75260d644c17SKarl Rupp 
75279566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
75284a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7529552f7358SJed Brown   if (ierr) {
7530552f7358SJed Brown     PetscMPIInt    rank;
7531552f7358SJed Brown 
75329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
75339566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
75349566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
75359566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75369566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7537c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values");
7538552f7358SJed Brown   }
75394a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75404a1e0b3eSMatthew G. Knepley     PetscInt i;
75419566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
75429566063dSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]));
75439566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
75444a1e0b3eSMatthew G. Knepley   }
754571f0bbf9SMatthew G. Knepley 
75469566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75479566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
754871f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75494acb8e1eSToby Isaac }
755071f0bbf9SMatthew G. Knepley 
75514a1e0b3eSMatthew G. Knepley /*@C
75524a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75534a1e0b3eSMatthew G. Knepley 
75544a1e0b3eSMatthew G. Knepley   Not collective
75554a1e0b3eSMatthew G. Knepley 
75564a1e0b3eSMatthew G. Knepley   Input Parameters:
75574a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
75584a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
75594a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
75604a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
75614a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
75624a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
75634a1e0b3eSMatthew G. Knepley . A - The matrix
75644a1e0b3eSMatthew G. Knepley . point - The point in the DMs
75654a1e0b3eSMatthew G. Knepley . values - The array of values
75664a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75674a1e0b3eSMatthew G. Knepley 
75684a1e0b3eSMatthew G. Knepley   Level: intermediate
75694a1e0b3eSMatthew G. Knepley 
75704a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
75714a1e0b3eSMatthew G. Knepley @*/
757271f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
757371f0bbf9SMatthew G. Knepley {
757471f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
757571f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
757671f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
757771f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
757871f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
757971f0bbf9SMatthew G. Knepley 
758071f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
758171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
75829566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
758371f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
75849566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
758571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
758671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
75879566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
758871f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
75899566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
759071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
759171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
759271f0bbf9SMatthew G. Knepley 
75939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
75949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
759571f0bbf9SMatthew G. Knepley 
75969566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
75974a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
759871f0bbf9SMatthew G. Knepley   if (ierr) {
759971f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
760071f0bbf9SMatthew G. Knepley 
76019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
76029566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
76039566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
76049566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76059566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values));
76069566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
76079566063dSJacob Faibussowitsch     PetscCall(ierr);
7608d3d1a6afSToby Isaac   }
760971f0bbf9SMatthew G. Knepley 
76109566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76119566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
76129566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7613552f7358SJed Brown   PetscFunctionReturn(0);
7614552f7358SJed Brown }
7615552f7358SJed Brown 
7616de41b84cSMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7617de41b84cSMatthew G. Knepley {
7618de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7619de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7620de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7621de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
762217c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7623de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7624412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
76254ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7626de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7627de41b84cSMatthew G. Knepley 
7628de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7629de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7630de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
76319566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7632de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
76339566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7634de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
76359566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7636de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
76379566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7638de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7639de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
76409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
76412c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
76429566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
76439566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7644de41b84cSMatthew G. Knepley   /* Column indices */
76459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
76464ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7647de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7648de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
76499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7650de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7651de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7652de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7653de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7654de41b84cSMatthew G. Knepley       ++q;
7655de41b84cSMatthew G. Knepley     }
7656de41b84cSMatthew G. Knepley   }
7657de41b84cSMatthew G. Knepley   numCPoints = q;
7658de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7659de41b84cSMatthew G. Knepley     PetscInt fdof;
7660de41b84cSMatthew G. Knepley 
76619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
76624ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7663de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7665de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7666de41b84cSMatthew G. Knepley     }
7667de41b84cSMatthew G. Knepley     numCIndices += dof;
7668de41b84cSMatthew G. Knepley   }
7669de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7670de41b84cSMatthew G. Knepley   /* Row indices */
76719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7672412e9a14SMatthew G. Knepley   {
7673012bc364SMatthew G. Knepley     DMPlexTransform tr;
7674012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7675012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7676012bc364SMatthew G. Knepley 
76779566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
76789566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
76799566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7680012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
76819566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7682412e9a14SMatthew G. Knepley   }
76839566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
7684de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7685de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
76869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7687de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
76889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
7689de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7690de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
76919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
76924ca5e9f5SMatthew G. Knepley         if (!dof) continue;
76934ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
76944ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7695de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7696de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7697de41b84cSMatthew G. Knepley         ++q;
7698de41b84cSMatthew G. Knepley       }
7699de41b84cSMatthew G. Knepley     }
77009566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7701de41b84cSMatthew G. Knepley   }
7702de41b84cSMatthew G. Knepley   numFPoints = q;
7703de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7704de41b84cSMatthew G. Knepley     PetscInt fdof;
7705de41b84cSMatthew G. Knepley 
77069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
77074ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7708de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
7710de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7711de41b84cSMatthew G. Knepley     }
7712de41b84cSMatthew G. Knepley     numFIndices += dof;
7713de41b84cSMatthew G. Knepley   }
7714de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7715de41b84cSMatthew G. Knepley 
77162c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
77172c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
77189566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77199566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7720de41b84cSMatthew G. Knepley   if (numFields) {
77214acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
77224acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
77234acb8e1eSToby Isaac 
77244acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7727de41b84cSMatthew G. Knepley     }
77284acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
77299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
77314acb8e1eSToby Isaac     }
77324acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
77339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
77354acb8e1eSToby Isaac     }
77364acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77379566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77389566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7739de41b84cSMatthew G. Knepley     }
7740de41b84cSMatthew G. Knepley   } else {
77414acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77424acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77434acb8e1eSToby Isaac 
77449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
77464acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77474acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77484acb8e1eSToby Isaac 
77499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
7751de41b84cSMatthew G. Knepley     }
77524acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77534acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77544acb8e1eSToby Isaac 
77559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
7757de41b84cSMatthew G. Knepley     }
77589566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77599566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
7760de41b84cSMatthew G. Knepley   }
77619566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77624acb8e1eSToby Isaac   /* TODO: flips */
7763de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7764de41b84cSMatthew G. Knepley   if (ierr) {
7765de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7766de41b84cSMatthew G. Knepley 
77679566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
77689566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
77699566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77709566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77719566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
77729566063dSJacob Faibussowitsch     PetscCall(ierr);
7773de41b84cSMatthew G. Knepley   }
77749566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
77759566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
77769566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77779566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7778de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7779de41b84cSMatthew G. Knepley }
7780de41b84cSMatthew G. Knepley 
77817c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
77827c927364SMatthew G. Knepley {
77837c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
77847c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
77857c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
778617c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7787412e9a14SMatthew G. Knepley   DMPolytopeType ct;
77887c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
77897c927364SMatthew G. Knepley 
77907c927364SMatthew G. Knepley   PetscFunctionBegin;
77917c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
77927c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
77939566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
77947c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
77959566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
77967c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
77979566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
77987c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
77999566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
78007c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
78019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
78022c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
78039566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
78049566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
78057c927364SMatthew G. Knepley   /* Column indices */
78069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78077c927364SMatthew G. Knepley   maxFPoints = numCPoints;
78087c927364SMatthew G. Knepley   /* Compress out points not in the section */
78097c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
78109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
78117c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
78127c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
78137c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
78147c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
78157c927364SMatthew G. Knepley       ++q;
78167c927364SMatthew G. Knepley     }
78177c927364SMatthew G. Knepley   }
78187c927364SMatthew G. Knepley   numCPoints = q;
78197c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
78207c927364SMatthew G. Knepley     PetscInt fdof;
78217c927364SMatthew G. Knepley 
78229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
78237c927364SMatthew G. Knepley     if (!dof) continue;
78247c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
78267c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
78277c927364SMatthew G. Knepley     }
78287c927364SMatthew G. Knepley     numCIndices += dof;
78297c927364SMatthew G. Knepley   }
78307c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
78317c927364SMatthew G. Knepley   /* Row indices */
78329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7833412e9a14SMatthew G. Knepley   {
7834012bc364SMatthew G. Knepley     DMPlexTransform tr;
7835012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7836012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7837012bc364SMatthew G. Knepley 
78389566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
78399566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
78409566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7841012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
78429566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7843412e9a14SMatthew G. Knepley   }
78449566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
78457c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78467c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
78487c927364SMatthew G. Knepley     /* Compress out points not in the section */
78499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
78507c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
78517c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78529566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
78537c927364SMatthew G. Knepley         if (!dof) continue;
78547c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
78557c927364SMatthew G. Knepley         if (s < q) continue;
78567c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
78577c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
78587c927364SMatthew G. Knepley         ++q;
78597c927364SMatthew G. Knepley       }
78607c927364SMatthew G. Knepley     }
78619566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
78627c927364SMatthew G. Knepley   }
78637c927364SMatthew G. Knepley   numFPoints = q;
78647c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
78657c927364SMatthew G. Knepley     PetscInt fdof;
78667c927364SMatthew G. Knepley 
78679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
78687c927364SMatthew G. Knepley     if (!dof) continue;
78697c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
78717c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
78727c927364SMatthew G. Knepley     }
78737c927364SMatthew G. Knepley     numFIndices += dof;
78747c927364SMatthew G. Knepley   }
78757c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
78767c927364SMatthew G. Knepley 
78772c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
78782c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
78797c927364SMatthew G. Knepley   if (numFields) {
78804acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
78814acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
78824acb8e1eSToby Isaac 
78834acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
78849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
78859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
78867c927364SMatthew G. Knepley     }
78874acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
78889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
78899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
78904acb8e1eSToby Isaac     }
78914acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
78929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
78939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
78944acb8e1eSToby Isaac     }
78954acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
78969566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
78979566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
78987c927364SMatthew G. Knepley     }
78997c927364SMatthew G. Knepley   } else {
79004acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
79014acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
79024acb8e1eSToby Isaac 
79039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79054acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
79064acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
79074acb8e1eSToby Isaac 
79089566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
79107c927364SMatthew G. Knepley     }
79114acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
79124acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
79134acb8e1eSToby Isaac 
79149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
79167c927364SMatthew G. Knepley     }
79179566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79189566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79197c927364SMatthew G. Knepley   }
79209566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
79219566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79227c927364SMatthew G. Knepley   PetscFunctionReturn(0);
79237c927364SMatthew G. Knepley }
79247c927364SMatthew G. Knepley 
79257cd05799SMatthew G. Knepley /*@C
79267cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
79277cd05799SMatthew G. Knepley 
79287cd05799SMatthew G. Knepley   Input Parameter:
79297cd05799SMatthew G. Knepley . dm   - The DMPlex object
79307cd05799SMatthew G. Knepley 
79317cd05799SMatthew G. Knepley   Output Parameter:
79327cd05799SMatthew G. Knepley . cellHeight - The height of a cell
79337cd05799SMatthew G. Knepley 
79347cd05799SMatthew G. Knepley   Level: developer
79357cd05799SMatthew G. Knepley 
79367cd05799SMatthew G. Knepley .seealso DMPlexSetVTKCellHeight()
79377cd05799SMatthew G. Knepley @*/
7938552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7939552f7358SJed Brown {
7940552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7941552f7358SJed Brown 
7942552f7358SJed Brown   PetscFunctionBegin;
7943552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7944dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
7945552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7946552f7358SJed Brown   PetscFunctionReturn(0);
7947552f7358SJed Brown }
7948552f7358SJed Brown 
79497cd05799SMatthew G. Knepley /*@C
79507cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79517cd05799SMatthew G. Knepley 
79527cd05799SMatthew G. Knepley   Input Parameters:
79537cd05799SMatthew G. Knepley + dm   - The DMPlex object
79547cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79557cd05799SMatthew G. Knepley 
79567cd05799SMatthew G. Knepley   Level: developer
79577cd05799SMatthew G. Knepley 
79587cd05799SMatthew G. Knepley .seealso DMPlexGetVTKCellHeight()
79597cd05799SMatthew G. Knepley @*/
7960552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
7961552f7358SJed Brown {
7962552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7963552f7358SJed Brown 
7964552f7358SJed Brown   PetscFunctionBegin;
7965552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7966552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7967552f7358SJed Brown   PetscFunctionReturn(0);
7968552f7358SJed Brown }
7969552f7358SJed Brown 
7970e6139122SMatthew G. Knepley /*@
7971e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
7972e6139122SMatthew G. Knepley 
7973e6139122SMatthew G. Knepley   Input Parameter:
7974e6139122SMatthew G. Knepley . dm - The DMPlex object
7975e6139122SMatthew G. Knepley 
7976e6139122SMatthew G. Knepley   Output Parameters:
79772a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
79782a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
7979e6139122SMatthew G. Knepley 
79802a9f31c0SMatthew G. Knepley   Level: advanced
7981e6139122SMatthew G. Knepley 
79828065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
7983e6139122SMatthew G. Knepley @*/
7984e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
7985e6139122SMatthew G. Knepley {
7986412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
7987e6139122SMatthew G. Knepley 
7988e6139122SMatthew G. Knepley   PetscFunctionBegin;
7989e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
79919566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
7992e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
7993e6139122SMatthew G. Knepley }
7994e6139122SMatthew G. Knepley 
79959886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
7996552f7358SJed Brown {
7997552f7358SJed Brown   PetscSection   section, globalSection;
7998552f7358SJed Brown   PetscInt      *numbers, p;
7999552f7358SJed Brown 
8000552f7358SJed Brown   PetscFunctionBegin;
80019566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
80029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
8003552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80049566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(section, p, 1));
8005552f7358SJed Brown   }
80069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
80079566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
80089566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8009552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]));
8011ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
8012ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
8013552f7358SJed Brown   }
80149566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8015ef48cebcSMatthew G. Knepley   if (globalSize) {
8016ef48cebcSMatthew G. Knepley     PetscLayout layout;
80179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout));
80189566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
80199566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8020ef48cebcSMatthew G. Knepley   }
80219566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
80229566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
8023552f7358SJed Brown   PetscFunctionReturn(0);
8024552f7358SJed Brown }
8025552f7358SJed Brown 
802681ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8027552f7358SJed Brown {
8028412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
8029552f7358SJed Brown 
8030552f7358SJed Brown   PetscFunctionBegin;
80319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
80329566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
80339566063dSJacob Faibussowitsch   else               PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
80349566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
803581ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8036552f7358SJed Brown }
803781ed3555SMatthew G. Knepley 
80388dab3259SMatthew G. Knepley /*@
80397cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
80407cd05799SMatthew G. Knepley 
80417cd05799SMatthew G. Knepley   Input Parameter:
80427cd05799SMatthew G. Knepley . dm   - The DMPlex object
80437cd05799SMatthew G. Knepley 
80447cd05799SMatthew G. Knepley   Output Parameter:
80457cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80467cd05799SMatthew G. Knepley 
80477cd05799SMatthew G. Knepley   Level: developer
80487cd05799SMatthew G. Knepley 
80497cd05799SMatthew G. Knepley .seealso DMPlexGetVertexNumbering()
80507cd05799SMatthew G. Knepley @*/
805181ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
805281ed3555SMatthew G. Knepley {
805381ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
805481ed3555SMatthew G. Knepley 
805581ed3555SMatthew G. Knepley   PetscFunctionBegin;
805681ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80579566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8058552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8059552f7358SJed Brown   PetscFunctionReturn(0);
8060552f7358SJed Brown }
8061552f7358SJed Brown 
806281ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
806381ed3555SMatthew G. Knepley {
8064412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
806581ed3555SMatthew G. Knepley 
806681ed3555SMatthew G. Knepley   PetscFunctionBegin;
806781ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
80699566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
807081ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
807181ed3555SMatthew G. Knepley }
807281ed3555SMatthew G. Knepley 
80738dab3259SMatthew G. Knepley /*@
80746aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
80757cd05799SMatthew G. Knepley 
80767cd05799SMatthew G. Knepley   Input Parameter:
80777cd05799SMatthew G. Knepley . dm   - The DMPlex object
80787cd05799SMatthew G. Knepley 
80797cd05799SMatthew G. Knepley   Output Parameter:
80807cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
80817cd05799SMatthew G. Knepley 
80827cd05799SMatthew G. Knepley   Level: developer
80837cd05799SMatthew G. Knepley 
80847cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
80857cd05799SMatthew G. Knepley @*/
8086552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8087552f7358SJed Brown {
8088552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
8089552f7358SJed Brown 
8090552f7358SJed Brown   PetscFunctionBegin;
8091552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80929566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8093552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8094552f7358SJed Brown   PetscFunctionReturn(0);
8095552f7358SJed Brown }
8096552f7358SJed Brown 
80978dab3259SMatthew G. Knepley /*@
80987cd05799SMatthew G. Knepley   DMPlexCreatePointNumbering - Create a global numbering for all points on this process
80997cd05799SMatthew G. Knepley 
81007cd05799SMatthew G. Knepley   Input Parameter:
81017cd05799SMatthew G. Knepley . dm   - The DMPlex object
81027cd05799SMatthew G. Knepley 
81037cd05799SMatthew G. Knepley   Output Parameter:
81047cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
81057cd05799SMatthew G. Knepley 
81067cd05799SMatthew G. Knepley   Level: developer
81077cd05799SMatthew G. Knepley 
81087cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
81097cd05799SMatthew G. Knepley @*/
8110ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8111ef48cebcSMatthew G. Knepley {
8112ef48cebcSMatthew G. Knepley   IS             nums[4];
8113862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
8114ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
8115ef48cebcSMatthew G. Knepley 
8116ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8117ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
81198abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
81209566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
8121862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8122862913ffSStefano Zampini     PetscInt end;
8123862913ffSStefano Zampini 
8124862913ffSStefano Zampini     depths[d] = depth-d;
81259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
8126862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
8127862913ffSStefano Zampini   }
81289566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithArray(depth+1, starts, depths));
81299566063dSJacob Faibussowitsch   PetscCallMPI(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm)));
8130862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
81312c71b3e2SJacob Faibussowitsch     PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]);
8132862913ffSStefano Zampini   }
8133ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8134ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8135ef48cebcSMatthew G. Knepley 
81369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
81379566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8138ef48cebcSMatthew G. Knepley     shift += gsize;
8139ef48cebcSMatthew G. Knepley   }
81409566063dSJacob Faibussowitsch   PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers));
81419566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
8142ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8143ef48cebcSMatthew G. Knepley }
8144ef48cebcSMatthew G. Knepley 
814508a22f4bSMatthew G. Knepley /*@
814608a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
814708a22f4bSMatthew G. Knepley 
814808a22f4bSMatthew G. Knepley   Input Parameter:
814908a22f4bSMatthew G. Knepley . dm - The DMPlex object
815008a22f4bSMatthew G. Knepley 
815108a22f4bSMatthew G. Knepley   Output Parameter:
815208a22f4bSMatthew G. Knepley . ranks - The rank field
815308a22f4bSMatthew G. Knepley 
815408a22f4bSMatthew G. Knepley   Options Database Keys:
815508a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
815608a22f4bSMatthew G. Knepley 
815708a22f4bSMatthew G. Knepley   Level: intermediate
815808a22f4bSMatthew G. Knepley 
815908a22f4bSMatthew G. Knepley .seealso: DMView()
816008a22f4bSMatthew G. Knepley @*/
816108a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
816208a22f4bSMatthew G. Knepley {
816308a22f4bSMatthew G. Knepley   DM             rdm;
816408a22f4bSMatthew G. Knepley   PetscFE        fe;
816508a22f4bSMatthew G. Knepley   PetscScalar   *r;
816608a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8167a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
816808a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8169a55f9a55SMatthew G. Knepley   PetscBool      simplex;
817008a22f4bSMatthew G. Knepley 
817108a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8172f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8173f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
81749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
81759566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
81769566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
81779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
81789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8179a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
81809566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
81819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "rank"));
81829566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
81839566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
81849566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
81859566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
81869566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition"));
81879566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
818808a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
818908a22f4bSMatthew G. Knepley     PetscScalar *lr;
819008a22f4bSMatthew G. Knepley 
81919566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
819271f09efeSPierre Jolivet     if (lr) *lr = rank;
819308a22f4bSMatthew G. Knepley   }
81949566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
81959566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
819608a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
819708a22f4bSMatthew G. Knepley }
819808a22f4bSMatthew G. Knepley 
8199ca8062c8SMatthew G. Knepley /*@
820018e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
820118e14f0cSMatthew G. Knepley 
820218e14f0cSMatthew G. Knepley   Input Parameters:
820318e14f0cSMatthew G. Knepley + dm    - The DMPlex
820418e14f0cSMatthew G. Knepley - label - The DMLabel
820518e14f0cSMatthew G. Knepley 
820618e14f0cSMatthew G. Knepley   Output Parameter:
820718e14f0cSMatthew G. Knepley . val - The label value field
820818e14f0cSMatthew G. Knepley 
820918e14f0cSMatthew G. Knepley   Options Database Keys:
821018e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
821118e14f0cSMatthew G. Knepley 
821218e14f0cSMatthew G. Knepley   Level: intermediate
821318e14f0cSMatthew G. Knepley 
821418e14f0cSMatthew G. Knepley .seealso: DMView()
821518e14f0cSMatthew G. Knepley @*/
821618e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
821718e14f0cSMatthew G. Knepley {
821818e14f0cSMatthew G. Knepley   DM             rdm;
821918e14f0cSMatthew G. Knepley   PetscFE        fe;
822018e14f0cSMatthew G. Knepley   PetscScalar   *v;
822118e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
822218e14f0cSMatthew G. Knepley 
822318e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
822418e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
822518e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
822618e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
82279566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82289566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82299566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
82309566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "label_value"));
82319566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82329566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82339566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82359566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
82369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *val, "label_value"));
82379566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
823818e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
823918e14f0cSMatthew G. Knepley     PetscScalar *lv;
824018e14f0cSMatthew G. Knepley     PetscInt     cval;
824118e14f0cSMatthew G. Knepley 
82429566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
82439566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
824418e14f0cSMatthew G. Knepley     *lv = cval;
824518e14f0cSMatthew G. Knepley   }
82469566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
82479566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
824818e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
824918e14f0cSMatthew G. Knepley }
825018e14f0cSMatthew G. Knepley 
825118e14f0cSMatthew G. Knepley /*@
8252ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8253ca8062c8SMatthew G. Knepley 
825469916449SMatthew G. Knepley   Input Parameter:
825569916449SMatthew G. Knepley . dm - The DMPlex object
8256ca8062c8SMatthew G. Knepley 
825795eb5ee5SVaclav Hapla   Notes:
825895eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
825995eb5ee5SVaclav Hapla 
826095eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8261ca8062c8SMatthew G. Knepley 
8262ca8062c8SMatthew G. Knepley   Level: developer
8263ca8062c8SMatthew G. Knepley 
826495eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8265ca8062c8SMatthew G. Knepley @*/
8266ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8267ca8062c8SMatthew G. Knepley {
8268ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8269ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8270ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
827157beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
827257beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8273ca8062c8SMatthew G. Knepley 
8274ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8275ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
82769566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
82779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
82789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8279ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
82809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8281ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
82829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
82839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8284ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
828542e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
828642e66dfaSMatthew G. Knepley       PetscInt  d;
828742e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
828842e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
828942e66dfaSMatthew G. Knepley       }
82909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
82919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8292ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8293ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8294ca8062c8SMatthew G. Knepley       }
829542e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
82969566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p));
8297ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
82989566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]));
8299ca8062c8SMatthew G. Knepley         }
83009566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
83019566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]));
8302ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
83039566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]));
8304ca8062c8SMatthew G. Knepley         }
83059566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
830628b400f6SJacob Faibussowitsch         PetscCheck(!dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]);
830798921bdaSJacob Faibussowitsch         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]);
8308ca8062c8SMatthew G. Knepley       }
830942e66dfaSMatthew G. Knepley     }
83109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
831157beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
83129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
83139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8314ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
83159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
83169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8317ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
83189566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
831957beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8320ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8321ca8062c8SMatthew G. Knepley       }
8322ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
83239566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p));
8324ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
83259566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]));
8326ca8062c8SMatthew G. Knepley         }
83279566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
83289566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]));
8329ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
83309566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]));
8331ca8062c8SMatthew G. Knepley         }
83329566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
833398921bdaSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]);
8334ca8062c8SMatthew G. Knepley       }
8335ca8062c8SMatthew G. Knepley     }
8336ca8062c8SMatthew G. Knepley   }
833757beb4faSStefano Zampini   if (storagecheck) {
83389566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
83399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
83402c71b3e2SJacob Faibussowitsch     PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize);
834157beb4faSStefano Zampini   }
8342ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8343ca8062c8SMatthew G. Knepley }
8344ca8062c8SMatthew G. Knepley 
8345412e9a14SMatthew G. Knepley /*
8346412e9a14SMatthew 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.
8347412e9a14SMatthew G. Knepley */
8348412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8349412e9a14SMatthew G. Knepley {
8350412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8351412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8352412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8353412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8354412e9a14SMatthew G. Knepley 
8355412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8356412e9a14SMatthew G. Knepley   *unsplit = 0;
8357412e9a14SMatthew G. Knepley   switch (ct) {
8358b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
8359b5a892a1SMatthew G. Knepley       ptpoints[npt++] = c;
8360b5a892a1SMatthew G. Knepley       break;
8361412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
83629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
83639566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8364412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
83659566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8366412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8367412e9a14SMatthew G. Knepley       }
8368412e9a14SMatthew G. Knepley       break;
8369412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8370412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
83719566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
83729566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8373412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
83749566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
83759566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8376412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
83779566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8378412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8379412e9a14SMatthew G. Knepley             PetscInt p;
8380412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8381412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8382412e9a14SMatthew G. Knepley           }
8383412e9a14SMatthew G. Knepley         }
8384412e9a14SMatthew G. Knepley       }
8385412e9a14SMatthew G. Knepley       break;
8386412e9a14SMatthew G. Knepley     default: break;
8387412e9a14SMatthew G. Knepley   }
8388412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
83899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8390412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8391412e9a14SMatthew G. Knepley   }
8392412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8393412e9a14SMatthew G. Knepley }
8394412e9a14SMatthew G. Knepley 
8395ca8062c8SMatthew G. Knepley /*@
8396ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8397ca8062c8SMatthew G. Knepley 
8398ca8062c8SMatthew G. Knepley   Input Parameters:
8399ca8062c8SMatthew G. Knepley + dm - The DMPlex object
840058723a97SMatthew G. Knepley - cellHeight - Normally 0
8401ca8062c8SMatthew G. Knepley 
840295eb5ee5SVaclav Hapla   Notes:
840395eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
840425c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8405ca8062c8SMatthew G. Knepley 
840695eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
840795eb5ee5SVaclav Hapla 
8408ca8062c8SMatthew G. Knepley   Level: developer
8409ca8062c8SMatthew G. Knepley 
841095eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8411ca8062c8SMatthew G. Knepley @*/
841225c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8413ca8062c8SMatthew G. Knepley {
8414412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8415412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8416412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8417ca8062c8SMatthew G. Knepley 
8418ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8419ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84209566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
84219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
84229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8423412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8424412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8425412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
842658723a97SMatthew G. Knepley 
84279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
84282c71b3e2SJacob Faibussowitsch     PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c);
8429412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8430412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
84319566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
84322c71b3e2SJacob Faibussowitsch       PetscCheckFalse(coneSize != DMPolytopeTypeGetConeSize(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has cone size %D != %D", c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct));
8433412e9a14SMatthew G. Knepley     }
84349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
843558723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
843658723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8437412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
843858723a97SMatthew G. Knepley     }
84399566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8440412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8441412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8442412e9a14SMatthew G. Knepley       PetscInt unsplit;
844342363296SMatthew G. Knepley 
84449566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8445412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
844642363296SMatthew G. Knepley     }
84472c71b3e2SJacob Faibussowitsch     PetscCheckFalse(Nv != DMPolytopeTypeGetNumVertices(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D vertices != %D", c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct));
844842363296SMatthew G. Knepley   }
8449ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8450ca8062c8SMatthew G. Knepley }
84519bf0dad6SMatthew G. Knepley 
84529bf0dad6SMatthew G. Knepley /*@
84539bf0dad6SMatthew 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
84549bf0dad6SMatthew G. Knepley 
8455899ea2b8SJacob Faibussowitsch   Not Collective
8456899ea2b8SJacob Faibussowitsch 
84579bf0dad6SMatthew G. Knepley   Input Parameters:
84589bf0dad6SMatthew G. Knepley + dm - The DMPlex object
84599bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
84609bf0dad6SMatthew G. Knepley 
846145da879fSVaclav Hapla   Notes:
846245da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
846345da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
846445da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
846545da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
84669bf0dad6SMatthew G. Knepley 
846795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
846895eb5ee5SVaclav Hapla 
84699bf0dad6SMatthew G. Knepley   Level: developer
84709bf0dad6SMatthew G. Knepley 
847195eb5ee5SVaclav Hapla .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions()
84729bf0dad6SMatthew G. Knepley @*/
847325c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
84749bf0dad6SMatthew G. Knepley {
8475ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8476899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
84779bf0dad6SMatthew G. Knepley 
84789bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
84799bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84809566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interpEnum));
848145da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
848245da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) {
8483899ea2b8SJacob Faibussowitsch     PetscMPIInt rank;
8484899ea2b8SJacob Faibussowitsch     MPI_Comm    comm;
8485899ea2b8SJacob Faibussowitsch 
84869566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
84879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
848898921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank);
8489899ea2b8SJacob Faibussowitsch   }
8490899ea2b8SJacob Faibussowitsch 
84919566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
84929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
84939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8494ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
84959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
84963554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8497412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8498412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8499ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8500412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8501412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
85029bf0dad6SMatthew G. Knepley 
85039566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
85049566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8505412e9a14SMatthew G. Knepley       if (unsplit) continue;
85069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
85079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
85089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
85099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85109bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
85119bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
85129bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
85139bf0dad6SMatthew G. Knepley       }
85149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85152c71b3e2SJacob Faibussowitsch       PetscCheckFalse(coneSize != numFaces,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D faces but should have %D", c, DMPolytopeTypes[ct], coneSize, numFaces);
85169bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8517d4961f80SStefano Zampini         DMPolytopeType fct;
85189bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
85199bf0dad6SMatthew G. Knepley 
85209566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
85219566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
85229bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
85239bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85249bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85259bf0dad6SMatthew G. Knepley         }
85262c71b3e2SJacob Faibussowitsch         PetscCheckFalse(fnumCorners != faceSizes[f],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %D) of cell %D of type %s has %D vertices but should have %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]);
85279bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8528b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff+v]) {
8529b5a892a1SMatthew G. Knepley             PetscInt v1;
8530b5a892a1SMatthew G. Knepley 
85319566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
85329566063dSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]));
85339566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
85349566063dSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]));
85359566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
853698921bdaSJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d, ornt %D) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]);
8537b5a892a1SMatthew G. Knepley           }
85389bf0dad6SMatthew G. Knepley         }
85399566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8540412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
85419bf0dad6SMatthew G. Knepley       }
85429566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85439566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85449bf0dad6SMatthew G. Knepley     }
85453554e41dSMatthew G. Knepley   }
8546552f7358SJed Brown   PetscFunctionReturn(0);
8547552f7358SJed Brown }
85483913d7c8SMatthew G. Knepley 
8549bb6a34a8SMatthew G. Knepley /*@
8550bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8551bb6a34a8SMatthew G. Knepley 
8552bb6a34a8SMatthew G. Knepley   Input Parameter:
8553bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8554bb6a34a8SMatthew G. Knepley 
855595eb5ee5SVaclav Hapla   Notes:
855695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
855795eb5ee5SVaclav Hapla 
855895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8559bb6a34a8SMatthew G. Knepley 
8560bb6a34a8SMatthew G. Knepley   Level: developer
8561bb6a34a8SMatthew G. Knepley 
856295eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8563bb6a34a8SMatthew G. Knepley @*/
8564bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8565bb6a34a8SMatthew G. Knepley {
8566a2a9e04cSMatthew G. Knepley   Vec            coordinates;
8567bb6a34a8SMatthew G. Knepley   PetscReal      detJ, J[9], refVol = 1.0;
8568bb6a34a8SMatthew G. Knepley   PetscReal      vol;
8569412e9a14SMatthew G. Knepley   PetscBool      periodic;
857051a74b61SMatthew G. Knepley   PetscInt       dim, depth, dE, d, cStart, cEnd, c;
8571bb6a34a8SMatthew G. Knepley 
8572bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
85739566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
85749566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
857551a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
85769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
85779566063dSJacob Faibussowitsch   PetscCall(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL));
8578bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
85799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8580a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
85819566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8582412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8583412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8584412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8585412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8586412e9a14SMatthew G. Knepley 
85879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8588412e9a14SMatthew G. Knepley     switch (ct) {
8589412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8590412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8591412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8592412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8593412e9a14SMatthew G. Knepley       default: break;
8594412e9a14SMatthew G. Knepley     }
8595412e9a14SMatthew G. Knepley     switch (ct) {
8596412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8597412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8598412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8599a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8600412e9a14SMatthew G. Knepley         continue;
8601412e9a14SMatthew G. Knepley       default: break;
8602412e9a14SMatthew G. Knepley     }
86039566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8604412e9a14SMatthew G. Knepley     if (unsplit) continue;
86059566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
86062c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ);
86079566063dSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol));
8608412e9a14SMatthew G. Knepley     if (depth > 1 && !periodic) {
86099566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
86102c71b3e2SJacob Faibussowitsch       PetscCheckFalse(vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol);
86119566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol));
8612bb6a34a8SMatthew G. Knepley     }
8613bb6a34a8SMatthew G. Knepley   }
8614bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8615bb6a34a8SMatthew G. Knepley }
8616bb6a34a8SMatthew G. Knepley 
861703da9461SVaclav Hapla /*@
8618e83a0d2dSVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex.
861903da9461SVaclav Hapla 
862003da9461SVaclav Hapla   Input Parameters:
862103da9461SVaclav Hapla . dm - The DMPlex object
862203da9461SVaclav Hapla 
8623e83a0d2dSVaclav Hapla   Notes:
8624e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
86258918e3e2SVaclav Hapla   It currently checks only meshes with no partition overlapping.
862603da9461SVaclav Hapla 
862795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
862895eb5ee5SVaclav Hapla 
862903da9461SVaclav Hapla   Level: developer
863003da9461SVaclav Hapla 
863195eb5ee5SVaclav Hapla .seealso: DMGetPointSF(), DMSetFromOptions()
863203da9461SVaclav Hapla @*/
863303da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm)
863403da9461SVaclav Hapla {
8635f0cfc026SVaclav Hapla   PetscSF         pointSF;
8636f5869d18SMatthew G. Knepley   PetscInt        cellHeight, cStart, cEnd, l, nleaves, nroots, overlap;
8637f5869d18SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
8638f0cfc026SVaclav Hapla   PetscBool       distributed;
863903da9461SVaclav Hapla 
864003da9461SVaclav Hapla   PetscFunctionBegin;
864103da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86429566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &pointSF));
86439566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
8644f0cfc026SVaclav Hapla   if (!distributed) PetscFunctionReturn(0);
86459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetOverlap(dm, &overlap));
8646f0cfc026SVaclav Hapla   if (overlap) {
86479566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping"));
86488918e3e2SVaclav Hapla     PetscFunctionReturn(0);
86498918e3e2SVaclav Hapla   }
865028b400f6SJacob Faibussowitsch   PetscCheck(pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached");
86519566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL));
86522c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set");
86539566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
86549566063dSJacob Faibussowitsch   PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
865503da9461SVaclav Hapla 
8656ece87651SVaclav Hapla   /* 1) check there are no faces in 2D, cells in 3D, in interface */
86579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
86589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
8659f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8660f5869d18SMatthew G. Knepley     const PetscInt point = locals[l];
8661f5869d18SMatthew G. Knepley 
86622c71b3e2SJacob Faibussowitsch     PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point);
866303da9461SVaclav Hapla   }
8664ece87651SVaclav Hapla 
8665f5869d18SMatthew G. Knepley   /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
8666f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8667f5869d18SMatthew G. Knepley     const PetscInt  point = locals[l];
8668f5869d18SMatthew G. Knepley     const PetscInt *cone;
8669f5869d18SMatthew G. Knepley     PetscInt        coneSize, c, idx;
8670f5869d18SMatthew G. Knepley 
86719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
86729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
8673f5869d18SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
8674f5869d18SMatthew G. Knepley       if (!rootdegree[cone[c]]) {
86759566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
86762c71b3e2SJacob Faibussowitsch         PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]);
8677f5869d18SMatthew G. Knepley       }
8678f5869d18SMatthew G. Knepley     }
8679ece87651SVaclav Hapla   }
868003da9461SVaclav Hapla   PetscFunctionReturn(0);
868103da9461SVaclav Hapla }
868203da9461SVaclav Hapla 
8683b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight)
8684b5a892a1SMatthew G. Knepley {
8685b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
86869566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
86879566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
86889566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
86899566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
86909566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckPointSF(dm));
86919566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
8692b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8693b5a892a1SMatthew G. Knepley }
8694b5a892a1SMatthew G. Knepley 
8695068a5610SStefano Zampini typedef struct cell_stats
8696068a5610SStefano Zampini {
8697068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8698068a5610SStefano Zampini   PetscInt  count;
8699068a5610SStefano Zampini } cell_stats_t;
8700068a5610SStefano Zampini 
870125befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8702068a5610SStefano Zampini {
8703068a5610SStefano Zampini   PetscInt i, N = *len;
8704068a5610SStefano Zampini 
8705068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8706068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8707068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8708068a5610SStefano Zampini 
8709068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8710068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8711068a5610SStefano Zampini     B->sum += A->sum;
8712068a5610SStefano Zampini     B->squaresum += A->squaresum;
8713068a5610SStefano Zampini     B->count += A->count;
8714068a5610SStefano Zampini   }
8715068a5610SStefano Zampini }
8716068a5610SStefano Zampini 
8717068a5610SStefano Zampini /*@
871843fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8719068a5610SStefano Zampini 
87208261a58bSMatthew G. Knepley   Collective on dm
87218261a58bSMatthew G. Knepley 
8722068a5610SStefano Zampini   Input Parameters:
8723068a5610SStefano Zampini + dm        - The DMPlex object
872443fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
872543fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8726068a5610SStefano Zampini 
872795eb5ee5SVaclav Hapla   Notes:
872895eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
872995eb5ee5SVaclav Hapla 
873095eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8731068a5610SStefano Zampini 
8732068a5610SStefano Zampini   Level: developer
8733068a5610SStefano Zampini 
8734f108dbd7SJacob Faibussowitsch .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality()
8735068a5610SStefano Zampini @*/
873643fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8737068a5610SStefano Zampini {
8738068a5610SStefano Zampini   DM             dmCoarse;
873943fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
874043fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
874143fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
874243fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8743412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
874443fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8745068a5610SStefano Zampini 
8746068a5610SStefano Zampini   PetscFunctionBegin;
8747068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8748068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8749068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8750068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8751068a5610SStefano Zampini   stats.count = 0;
8752068a5610SStefano Zampini 
87539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
87549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
87559566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm,&cdim));
87569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
87579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd));
87589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd));
8759412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8760068a5610SStefano Zampini     PetscInt  i;
8761068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8762068a5610SStefano Zampini 
87639566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ));
87642c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c);
876543fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8766068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8767068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8768068a5610SStefano Zampini     }
8769068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8770068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8771068a5610SStefano Zampini 
8772068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8773068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8774068a5610SStefano Zampini     stats.sum       += cond;
8775068a5610SStefano Zampini     stats.squaresum += cond2;
8776068a5610SStefano Zampini     stats.count++;
87778261a58bSMatthew G. Knepley     if (output && cond > limit) {
877843fa8764SMatthew G. Knepley       PetscSection coordSection;
877943fa8764SMatthew G. Knepley       Vec          coordsLocal;
878043fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
878143fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
878243fa8764SMatthew G. Knepley 
87839566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
87849566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
87859566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
87869566063dSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond));
878743fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
87889566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %D: (", i));
878943fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
87909566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
87919566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d])));
879243fa8764SMatthew G. Knepley         }
87939566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
879443fa8764SMatthew G. Knepley       }
87959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
879643fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
879743fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
879843fa8764SMatthew G. Knepley 
879943fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
880043fa8764SMatthew G. Knepley           PetscReal len;
880143fa8764SMatthew G. Knepley 
88029566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
88039566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %D: length %g\n", edge, (double) len));
880443fa8764SMatthew G. Knepley         }
880543fa8764SMatthew G. Knepley       }
88069566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
88079566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
880843fa8764SMatthew G. Knepley     }
8809068a5610SStefano Zampini   }
88109566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
8811068a5610SStefano Zampini 
8812068a5610SStefano Zampini   if (size > 1) {
8813068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8814068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8815068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8816068a5610SStefano Zampini     MPI_Op        statReduce;
8817068a5610SStefano Zampini 
88189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType));
88199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
88209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
88219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm));
88229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
88239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
8824068a5610SStefano Zampini   } else {
88259566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats,&stats,1));
8826068a5610SStefano Zampini   }
8827dd400576SPatrick Sanan   if (rank == 0) {
8828068a5610SStefano Zampini     count = globalStats.count;
8829068a5610SStefano Zampini     min   = globalStats.min;
8830068a5610SStefano Zampini     max   = globalStats.max;
8831068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8832068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8833068a5610SStefano Zampini   }
8834068a5610SStefano Zampini 
8835068a5610SStefano Zampini   if (output) {
88369566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"Mesh with %D cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev));
8837068a5610SStefano Zampini   }
88389566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J,invJ));
8839068a5610SStefano Zampini 
88409566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm,&dmCoarse));
8841068a5610SStefano Zampini   if (dmCoarse) {
8842068a5610SStefano Zampini     PetscBool isplex;
8843068a5610SStefano Zampini 
88449566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex));
8845068a5610SStefano Zampini     if (isplex) {
88469566063dSJacob Faibussowitsch       PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit));
8847068a5610SStefano Zampini     }
8848068a5610SStefano Zampini   }
8849068a5610SStefano Zampini   PetscFunctionReturn(0);
8850068a5610SStefano Zampini }
8851068a5610SStefano Zampini 
8852f108dbd7SJacob Faibussowitsch /*@
8853f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8854f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8855f108dbd7SJacob Faibussowitsch 
88566ed19f2fSJacob Faibussowitsch   Collective on dm
8857f108dbd7SJacob Faibussowitsch 
8858f108dbd7SJacob Faibussowitsch   Input Parameters:
8859f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8860f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8861f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8862f108dbd7SJacob Faibussowitsch 
8863f108dbd7SJacob Faibussowitsch   Output Parameters:
8864f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8865f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8866f108dbd7SJacob Faibussowitsch 
8867f108dbd7SJacob Faibussowitsch   Options Database Keys:
8868f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8869f108dbd7SJacob Faibussowitsch supported.
8870f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8871f108dbd7SJacob Faibussowitsch 
8872f108dbd7SJacob Faibussowitsch   Notes:
8873f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8874f108dbd7SJacob Faibussowitsch 
8875f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8876f108dbd7SJacob Faibussowitsch 
8877f108dbd7SJacob 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
8878f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8879f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8880f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8881f108dbd7SJacob Faibussowitsch 
8882f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8883f108dbd7SJacob Faibussowitsch 
8884f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8885f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8886f108dbd7SJacob Faibussowitsch 
8887f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8888f108dbd7SJacob Faibussowitsch 
8889f108dbd7SJacob Faibussowitsch   Level: intermediate
8890f108dbd7SJacob Faibussowitsch 
8891f108dbd7SJacob Faibussowitsch .seealso: DMPlexCheckCellShape(), DMCreateLabel()
8892f108dbd7SJacob Faibussowitsch @*/
8893f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
8894f108dbd7SJacob Faibussowitsch {
88956ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
88966ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
88976ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
8898f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
88996ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
8900f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
8901f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
8902f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
8903f108dbd7SJacob Faibussowitsch   IS                      glob;
8904f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
8905f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
8906f108dbd7SJacob Faibussowitsch 
8907f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8908f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89096ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
8910f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
89116bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
89129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
89139566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
89142c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc);
89156ed19f2fSJacob Faibussowitsch   {
89166ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
89176ed19f2fSJacob Faibussowitsch 
89189566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
8919f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
8920f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
8921f108dbd7SJacob Faibussowitsch 
89229566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
892398921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
8924f108dbd7SJacob Faibussowitsch     }
89256ed19f2fSJacob Faibussowitsch   }
8926f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
8927f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
89289566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
89299566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
89306ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
89319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
89329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
89339566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
89349566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
89359566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
89369566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
89379566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
89389566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE));
89399566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
89409566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
89419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
89429566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
89439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
89449566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
89459566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
89469566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
89479566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
89489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
89496ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
89506ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
8951f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
8952f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
8953898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
8954f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
8955f108dbd7SJacob Faibussowitsch 
89566ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
8957f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
8958f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
89599566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
89609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
8961f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
89629566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
89636ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
89646ed19f2fSJacob Faibussowitsch       PetscInt         i;
89656ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
8966f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
8967f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
8968f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
8969f108dbd7SJacob Faibussowitsch 
8970f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
8971f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
89729566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
8973f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
89746ed19f2fSJacob Faibussowitsch       {
89756ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
89766ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
89776ed19f2fSJacob Faibussowitsch 
89789566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
89799566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
89809566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
89816ed19f2fSJacob Faibussowitsch       }
8982f108dbd7SJacob Faibussowitsch 
8983f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
8984f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
8985f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
8986f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
8987f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
8988addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
8989addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
8990addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
8991f108dbd7SJacob Faibussowitsch       }
8992addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
8993addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
8994addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
8995f108dbd7SJacob Faibussowitsch 
8996f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
8997f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
8998f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
8999f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
9000f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
9001f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9002f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
9003f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
9004f108dbd7SJacob Faibussowitsch       }
9005f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
9006f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
9007f108dbd7SJacob Faibussowitsch       }
9008f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
9009f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
9010f108dbd7SJacob Faibussowitsch       }
9011f108dbd7SJacob Faibussowitsch     }
90129566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
90139566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9014f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
90156ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9016f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
90179566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9018f108dbd7SJacob Faibussowitsch     }
9019f108dbd7SJacob Faibussowitsch   }
90209566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES));
90219566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
90229566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
90239566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
90249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
90259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9026f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
90279566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9028f108dbd7SJacob Faibussowitsch   }
90299566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
90309566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
90319566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9032f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9033f108dbd7SJacob Faibussowitsch }
9034f108dbd7SJacob Faibussowitsch 
90351eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
90361eb70e55SToby Isaac  * interpolator construction */
90371eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
90381eb70e55SToby Isaac {
90391eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
90401eb70e55SToby Isaac   PetscSF        sf;
90411eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
90421eb70e55SToby Isaac 
90431eb70e55SToby Isaac   PetscFunctionBegin;
90441eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
90451eb70e55SToby Isaac   PetscValidPointer(odm,2);
90469566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
90479566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
90489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm)));
90491eb70e55SToby Isaac   if (!ghasConstraints) {
90509566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
90511eb70e55SToby Isaac     *odm = dm;
90521eb70e55SToby Isaac     PetscFunctionReturn(0);
90531eb70e55SToby Isaac   }
90549566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
90559566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
90569566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
90579566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
90589566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
90599566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
90609566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
90611eb70e55SToby Isaac   PetscFunctionReturn(0);
90621eb70e55SToby Isaac }
90631eb70e55SToby Isaac 
90641eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
90651eb70e55SToby Isaac {
90661eb70e55SToby Isaac   DM             dmco, dmfo;
90671eb70e55SToby Isaac   Mat            interpo;
90681eb70e55SToby Isaac   Vec            rscale;
90691eb70e55SToby Isaac   Vec            cglobalo, clocal;
90701eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
90711eb70e55SToby Isaac   PetscBool      regular;
90721eb70e55SToby Isaac 
90731eb70e55SToby Isaac   PetscFunctionBegin;
90749566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
90759566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
90769566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
90779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
90789566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
90799566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
90809566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
90819566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
90829566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
90839566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
90849566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
90859566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
90869566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
90879566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
90889566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
90899566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
90909566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
90919566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
90929566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
90939566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
90949566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
90959566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
90969566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
90979566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
90981eb70e55SToby Isaac   *shift = fglobal;
90999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
91009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
91019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
91029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
91039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
91049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
91059566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
91069566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
91071eb70e55SToby Isaac   PetscFunctionReturn(0);
91081eb70e55SToby Isaac }
91091eb70e55SToby Isaac 
91101eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
91111eb70e55SToby Isaac {
91121eb70e55SToby Isaac   PetscObject    shifto;
91131eb70e55SToby Isaac   Vec            shift;
91141eb70e55SToby Isaac 
91151eb70e55SToby Isaac   PetscFunctionBegin;
91161eb70e55SToby Isaac   if (!interp) {
91171eb70e55SToby Isaac     Vec rscale;
91181eb70e55SToby Isaac 
91199566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
91209566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
91211eb70e55SToby Isaac   } else {
91229566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
91231eb70e55SToby Isaac   }
91249566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
91251eb70e55SToby Isaac   if (!shifto) {
91269566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
91279566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift));
91281eb70e55SToby Isaac     shifto = (PetscObject) shift;
91299566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
91301eb70e55SToby Isaac   }
91311eb70e55SToby Isaac   shift = (Vec) shifto;
91329566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
91339566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
91349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
91351eb70e55SToby Isaac   PetscFunctionReturn(0);
91361eb70e55SToby Isaac }
91371eb70e55SToby Isaac 
9138bceba477SMatthew G. Knepley /* Pointwise interpolation
9139bceba477SMatthew G. Knepley      Just code FEM for now
9140bceba477SMatthew G. Knepley      u^f = I u^c
91414ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
91424ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
91434ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9144bceba477SMatthew G. Knepley */
9145bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9146bceba477SMatthew G. Knepley {
9147bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
9148bceba477SMatthew G. Knepley   PetscInt       m, n;
9149a063dac3SMatthew G. Knepley   void          *ctx;
915068132eb9SMatthew G. Knepley   DM             cdm;
9151cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9152bceba477SMatthew G. Knepley 
9153bceba477SMatthew G. Knepley   PetscFunctionBegin;
91549566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
91559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
91569566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
91579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
915868132eb9SMatthew G. Knepley 
91599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
91609566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation));
91619566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
91629566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
91639566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
916468132eb9SMatthew G. Knepley 
91659566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
91669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
91679566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
91689566063dSJacob Faibussowitsch   else                                            PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
91699566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
91704db47ee9SStefano Zampini   if (scaling) {
91715d1c2e58SMatthew G. Knepley     /* Use naive scaling */
91729566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
91734db47ee9SStefano Zampini   }
9174a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9175a063dac3SMatthew G. Knepley }
9176bceba477SMatthew G. Knepley 
91776dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9178a063dac3SMatthew G. Knepley {
91796dbf9973SLawrence Mitchell   VecScatter     ctx;
918090748bafSMatthew G. Knepley 
9181a063dac3SMatthew G. Knepley   PetscFunctionBegin;
91829566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
91839566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
91849566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
9185bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9186bceba477SMatthew G. Knepley }
9187bceba477SMatthew G. Knepley 
91883e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
91893e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
91903e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
91913e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
91923e9753d6SMatthew G. Knepley {
919300635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
919400635df3SMatthew G. Knepley   PetscInt       c;
919500635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
91963e9753d6SMatthew G. Knepley }
91973e9753d6SMatthew G. Knepley 
9198b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9199b4937a87SMatthew G. Knepley {
9200b4937a87SMatthew G. Knepley   DM             dmc;
9201b4937a87SMatthew G. Knepley   PetscDS        ds;
9202b4937a87SMatthew G. Knepley   Vec            ones, locmass;
9203b4937a87SMatthew G. Knepley   IS             cellIS;
9204b4937a87SMatthew G. Knepley   PetscFormKey   key;
9205b4937a87SMatthew G. Knepley   PetscInt       depth;
9206b4937a87SMatthew G. Knepley 
9207b4937a87SMatthew G. Knepley   PetscFunctionBegin;
92089566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
92099566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
92109566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
92119566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92129566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
92139566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
92149566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
92159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
92169566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92179566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
92189566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9219b4937a87SMatthew G. Knepley   key.label = NULL;
9220b4937a87SMatthew G. Knepley   key.value = 0;
9221b4937a87SMatthew G. Knepley   key.field = 0;
9222b4937a87SMatthew G. Knepley   key.part  = 0;
92239566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
92249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
92259566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
92269566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
92279566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
92289566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
92299566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
92309566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
9231b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9232b4937a87SMatthew G. Knepley }
9233b4937a87SMatthew G. Knepley 
9234bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9235bd041c0cSMatthew G. Knepley {
9236bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
9237bd041c0cSMatthew G. Knepley   PetscInt       m, n;
9238bd041c0cSMatthew G. Knepley   void          *ctx;
9239bd041c0cSMatthew G. Knepley   DM             cdm;
9240bd041c0cSMatthew G. Knepley   PetscBool      regular;
9241bd041c0cSMatthew G. Knepley 
9242bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
92433e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
92443e9753d6SMatthew G. Knepley     DM            dmc;
92453e9753d6SMatthew G. Knepley     PetscDS       ds;
9246b4937a87SMatthew G. Knepley     PetscWeakForm wf;
92473e9753d6SMatthew G. Knepley     Vec           u;
92483e9753d6SMatthew G. Knepley     IS            cellIS;
924906ad1575SMatthew G. Knepley     PetscFormKey  key;
92503e9753d6SMatthew G. Knepley     PetscInt      depth;
92513e9753d6SMatthew G. Knepley 
92529566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
92539566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
92549566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
92559566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
92569566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
92579566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92589566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
92599566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmc, &u));
92609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
92619566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92629566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
92636528b96dSMatthew G. Knepley     key.label = NULL;
92646528b96dSMatthew G. Knepley     key.value = 0;
92656528b96dSMatthew G. Knepley     key.field = 0;
926606ad1575SMatthew G. Knepley     key.part  = 0;
92679566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
92689566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
92699566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmc, &u));
92709566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
92713e9753d6SMatthew G. Knepley   } else {
92729566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
92739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
92749566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
92759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9276bd041c0cSMatthew G. Knepley 
92779566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass));
92789566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
92799566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
92809566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9281bd041c0cSMatthew G. Knepley 
92829566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
92839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
92849566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
92859566063dSJacob Faibussowitsch     else                            PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
92863e9753d6SMatthew G. Knepley   }
92879566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9288bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9289bd041c0cSMatthew G. Knepley }
9290bd041c0cSMatthew G. Knepley 
92910aef6b92SMatthew G. Knepley /*@
92920aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
92930aef6b92SMatthew G. Knepley 
92940aef6b92SMatthew G. Knepley   Input Parameter:
92950aef6b92SMatthew G. Knepley . dm - The DMPlex object
92960aef6b92SMatthew G. Knepley 
92970aef6b92SMatthew G. Knepley   Output Parameter:
92980aef6b92SMatthew G. Knepley . regular - The flag
92990aef6b92SMatthew G. Knepley 
93000aef6b92SMatthew G. Knepley   Level: intermediate
93010aef6b92SMatthew G. Knepley 
93020aef6b92SMatthew G. Knepley .seealso: DMPlexSetRegularRefinement()
93030aef6b92SMatthew G. Knepley @*/
93040aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
93050aef6b92SMatthew G. Knepley {
93060aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93070aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9308dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
93090aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
93100aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93110aef6b92SMatthew G. Knepley }
93120aef6b92SMatthew G. Knepley 
93130aef6b92SMatthew G. Knepley /*@
93140aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93150aef6b92SMatthew G. Knepley 
93160aef6b92SMatthew G. Knepley   Input Parameters:
93170aef6b92SMatthew G. Knepley + dm - The DMPlex object
93180aef6b92SMatthew G. Knepley - regular - The flag
93190aef6b92SMatthew G. Knepley 
93200aef6b92SMatthew G. Knepley   Level: intermediate
93210aef6b92SMatthew G. Knepley 
93220aef6b92SMatthew G. Knepley .seealso: DMPlexGetRegularRefinement()
93230aef6b92SMatthew G. Knepley @*/
93240aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
93250aef6b92SMatthew G. Knepley {
93260aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93270aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93280aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
93290aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93300aef6b92SMatthew G. Knepley }
93310aef6b92SMatthew G. Knepley 
9332f7c74593SToby Isaac /* anchors */
9333a68b90caSToby Isaac /*@
9334f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9335ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9336a68b90caSToby Isaac 
9337e228b242SToby Isaac   not collective
9338a68b90caSToby Isaac 
9339f899ff85SJose E. Roman   Input Parameter:
9340a68b90caSToby Isaac . dm - The DMPlex object
9341a68b90caSToby Isaac 
9342a68b90caSToby Isaac   Output Parameters:
9343a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9344a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9345a68b90caSToby Isaac 
9346a68b90caSToby Isaac   Level: intermediate
9347a68b90caSToby Isaac 
9348ebdb1bfaSJed Brown .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints()
9349a68b90caSToby Isaac @*/
9350a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9351a68b90caSToby Isaac {
9352a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9353a68b90caSToby Isaac 
9354a68b90caSToby Isaac   PetscFunctionBegin;
9355a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93569566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9357a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9358a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9359a68b90caSToby Isaac   PetscFunctionReturn(0);
9360a68b90caSToby Isaac }
9361a68b90caSToby Isaac 
9362a68b90caSToby Isaac /*@
9363f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9364f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9365a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9366a68b90caSToby Isaac 
9367a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9368ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9369a68b90caSToby Isaac 
9370e228b242SToby Isaac   collective on dm
9371a68b90caSToby Isaac 
9372a68b90caSToby Isaac   Input Parameters:
9373a68b90caSToby Isaac + dm - The DMPlex object
9374e228b242SToby Isaac . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9375e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9376a68b90caSToby Isaac 
9377a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9378a68b90caSToby Isaac 
9379a68b90caSToby Isaac   Level: intermediate
9380a68b90caSToby Isaac 
9381ebdb1bfaSJed Brown .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints()
9382a68b90caSToby Isaac @*/
9383a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9384a68b90caSToby Isaac {
9385a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9386e228b242SToby Isaac   PetscMPIInt    result;
9387a68b90caSToby Isaac 
9388a68b90caSToby Isaac   PetscFunctionBegin;
9389a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9390e228b242SToby Isaac   if (anchorSection) {
9391e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
93929566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result));
93932c71b3e2SJacob Faibussowitsch     PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9394e228b242SToby Isaac   }
9395e228b242SToby Isaac   if (anchorIS) {
9396e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
93979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result));
93982c71b3e2SJacob Faibussowitsch     PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9399e228b242SToby Isaac   }
9400a68b90caSToby Isaac 
94019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
94029566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9403a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9404a68b90caSToby Isaac 
94059566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
94069566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9407a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9408a68b90caSToby Isaac 
9409cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9410a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9411a68b90caSToby Isaac     const PetscInt *anchors;
9412a68b90caSToby Isaac 
94139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
94149566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS,&size));
94159566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS,&anchors));
9416a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9417a68b90caSToby Isaac       PetscInt p;
9418a68b90caSToby Isaac 
9419a68b90caSToby Isaac       p = anchors[a];
9420a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9421a68b90caSToby Isaac         PetscInt dof;
9422a68b90caSToby Isaac 
94239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9424a68b90caSToby Isaac         if (dof) {
9425a68b90caSToby Isaac 
94269566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS,&anchors));
942798921bdaSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p);
9428a68b90caSToby Isaac         }
9429a68b90caSToby Isaac       }
9430a68b90caSToby Isaac     }
94319566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS,&anchors));
9432a68b90caSToby Isaac   }
9433f7c74593SToby Isaac   /* reset the generic constraints */
94349566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL));
9435a68b90caSToby Isaac   PetscFunctionReturn(0);
9436a68b90caSToby Isaac }
9437a68b90caSToby Isaac 
9438f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9439a68b90caSToby Isaac {
9440f7c74593SToby Isaac   PetscSection anchorSection;
94416995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9442a68b90caSToby Isaac 
9443a68b90caSToby Isaac   PetscFunctionBegin;
9444a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
94469566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec));
94479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
94486995de1eSToby Isaac   if (numFields) {
9449719ab38cSToby Isaac     PetscInt f;
94509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec,numFields));
9451719ab38cSToby Isaac 
9452719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9453719ab38cSToby Isaac       PetscInt numComp;
9454719ab38cSToby Isaac 
94559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section,f,&numComp));
94569566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp));
9457719ab38cSToby Isaac     }
94586995de1eSToby Isaac   }
94599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
94609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
94616995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
94626995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
94636995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
94649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd));
9465a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
94669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9467a68b90caSToby Isaac     if (dof) {
94689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,p,&dof));
94699566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec,p,dof));
9470a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
94719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section,p,f,&dof));
94729566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof));
9473a68b90caSToby Isaac       }
9474a68b90caSToby Isaac     }
9475a68b90caSToby Isaac   }
94769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
94779566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section"));
9478a68b90caSToby Isaac   PetscFunctionReturn(0);
9479a68b90caSToby Isaac }
9480a68b90caSToby Isaac 
9481f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9482a68b90caSToby Isaac {
9483f7c74593SToby Isaac   PetscSection   aSec;
9484ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
94850ac89760SToby Isaac   const PetscInt *anchors;
94860ac89760SToby Isaac   PetscInt       numFields, f;
948766ad2231SToby Isaac   IS             aIS;
9488e19f7ee6SMark Adams   MatType        mtype;
9489e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
94900ac89760SToby Isaac 
94910ac89760SToby Isaac   PetscFunctionBegin;
94920ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
94949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
94959566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,cMat));
94969566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat,m,n,m,n));
94979566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda));
94989566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda));
94999566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos));
95009566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos));
9501e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9502e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9503e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
95049566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat,mtype));
95059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
95069566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS,&anchors));
95076995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
95089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd));
95099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
95109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1,&i));
95110ac89760SToby Isaac   i[0] = 0;
95129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
95130ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9514f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9515f19733c5SToby Isaac 
95169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec,p,&rDof));
9517f19733c5SToby Isaac     if (!rDof) continue;
95189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
95190ac89760SToby Isaac     if (numFields) {
95200ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95210ac89760SToby Isaac         annz = 0;
9522f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9523f19733c5SToby Isaac           a = anchors[rOff + r];
9524ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95259566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
95260ac89760SToby Isaac           annz += aDof;
95270ac89760SToby Isaac         }
95289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
95299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off));
95300ac89760SToby Isaac         for (q = 0; q < dof; q++) {
95310ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
95320ac89760SToby Isaac         }
95330ac89760SToby Isaac       }
95342f7452b8SBarry Smith     } else {
95350ac89760SToby Isaac       annz = 0;
95369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
95370ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9538ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9539ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
95409566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,a,&aDof));
95410ac89760SToby Isaac         annz += aDof;
95420ac89760SToby Isaac       }
95439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
95449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec,p,&off));
95450ac89760SToby Isaac       for (q = 0; q < dof; q++) {
95460ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
95470ac89760SToby Isaac       }
95480ac89760SToby Isaac     }
95490ac89760SToby Isaac   }
95500ac89760SToby Isaac   nnz = i[m];
95519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&j));
95520ac89760SToby Isaac   offset = 0;
95530ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
95540ac89760SToby Isaac     if (numFields) {
95550ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95569566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
95570ac89760SToby Isaac         for (q = 0; q < dof; q++) {
95580ac89760SToby Isaac           PetscInt rDof, rOff, r;
95599566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec,p,&rDof));
95609566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
95610ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
95620ac89760SToby Isaac             PetscInt s;
95630ac89760SToby Isaac 
95640ac89760SToby Isaac             a = anchors[rOff + r];
9565ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
95669566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
95679566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff));
95680ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
95690ac89760SToby Isaac               j[offset++] = aOff + s;
95700ac89760SToby Isaac             }
95710ac89760SToby Isaac           }
95720ac89760SToby Isaac         }
95730ac89760SToby Isaac       }
95742f7452b8SBarry Smith     } else {
95759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
95760ac89760SToby Isaac       for (q = 0; q < dof; q++) {
95770ac89760SToby Isaac         PetscInt rDof, rOff, r;
95789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,p,&rDof));
95799566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
95800ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
95810ac89760SToby Isaac           PetscInt s;
95820ac89760SToby Isaac 
95830ac89760SToby Isaac           a = anchors[rOff + r];
9584ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
95869566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section,a,&aOff));
95870ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
95880ac89760SToby Isaac             j[offset++] = aOff + s;
95890ac89760SToby Isaac           }
95900ac89760SToby Isaac         }
95910ac89760SToby Isaac       }
95920ac89760SToby Isaac     }
95930ac89760SToby Isaac   }
95949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL));
95959566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
95969566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
95979566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
95980ac89760SToby Isaac   PetscFunctionReturn(0);
95990ac89760SToby Isaac }
96000ac89760SToby Isaac 
960166ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
960266ad2231SToby Isaac {
9603f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9604f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
960566ad2231SToby Isaac   Mat            cMat;
960666ad2231SToby Isaac 
960766ad2231SToby Isaac   PetscFunctionBegin;
960866ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
961066ad2231SToby Isaac   if (anchorSection) {
961144a7f3ddSMatthew G. Knepley     PetscInt Nf;
9612e228b242SToby Isaac 
96139566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
96149566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec));
96159566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat));
96169566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm,&Nf));
96179566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat));
96189566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL));
96199566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
96209566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
962166ad2231SToby Isaac   }
962266ad2231SToby Isaac   PetscFunctionReturn(0);
962366ad2231SToby Isaac }
9624a93c429eSMatthew G. Knepley 
9625a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9626a93c429eSMatthew G. Knepley {
9627a93c429eSMatthew G. Knepley   IS             subis;
9628a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9629a93c429eSMatthew G. Knepley 
9630a93c429eSMatthew G. Knepley   PetscFunctionBegin;
96319566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
963228b400f6SJacob Faibussowitsch   PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
963328b400f6SJacob Faibussowitsch   PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9634a93c429eSMatthew G. Knepley   /* Create subdomain */
96359566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
9636a93c429eSMatthew G. Knepley   /* Create submodel */
96379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
96389566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
96399566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
96409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
96419566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
9642a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9643a93c429eSMatthew G. Knepley   if (is) {
9644a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9645a93c429eSMatthew G. Knepley     IS              spIS;
9646a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9647a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9648a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9649a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9650a93c429eSMatthew G. Knepley 
96519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
96529566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
96539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
96549566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
96559566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
96569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
9657a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9658a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9659a93c429eSMatthew G. Knepley 
96609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
9661a93c429eSMatthew G. Knepley       if (gdof > 0) {
9662a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9663a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9664a93c429eSMatthew G. Knepley 
96659566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
96669566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
9667a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9668a93c429eSMatthew G. Knepley         }
9669a93c429eSMatthew G. Knepley         subSize += pSubSize;
9670a93c429eSMatthew G. Knepley         if (pSubSize) {
9671a93c429eSMatthew G. Knepley           if (bs < 0) {
9672a93c429eSMatthew G. Knepley             bs = pSubSize;
9673a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9674a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9675a93c429eSMatthew G. Knepley             bs = 1;
9676a93c429eSMatthew G. Knepley           }
9677a93c429eSMatthew G. Knepley         }
9678a93c429eSMatthew G. Knepley       }
9679a93c429eSMatthew G. Knepley     }
9680a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9681a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
96829566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
9683a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9684a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
96859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
9686a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9687a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9688a93c429eSMatthew G. Knepley 
96899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
9690a93c429eSMatthew G. Knepley       if (gdof > 0) {
9691a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9692a93c429eSMatthew G. Knepley 
96939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
9694a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9695a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9696a93c429eSMatthew G. Knepley 
9697a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9698a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
96999566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
97009566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
9701a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9702a93c429eSMatthew G. Knepley           }
97039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
97049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
9705a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9706a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9707a93c429eSMatthew G. Knepley           }
9708a93c429eSMatthew G. Knepley         }
9709a93c429eSMatthew G. Knepley       }
9710a93c429eSMatthew G. Knepley     }
97119566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
97129566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
9713a93c429eSMatthew G. Knepley     if (bs > 1) {
9714a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9715a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9716a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9717a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9718a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9719a93c429eSMatthew G. Knepley         }
9720a93c429eSMatthew G. Knepley       }
97219566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
9722a93c429eSMatthew G. Knepley     }
9723a93c429eSMatthew G. Knepley     /* Attach nullspace */
9724a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9725a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9726a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9727a93c429eSMatthew G. Knepley     }
9728a93c429eSMatthew G. Knepley     if (f < Nf) {
9729a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
97309566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
97316823f3c5SBlaise Bourdin 
97329566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace));
97339566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
9734a93c429eSMatthew G. Knepley     }
9735a93c429eSMatthew G. Knepley   }
9736a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9737a93c429eSMatthew G. Knepley }
9738c0f0dcc3SMatthew G. Knepley 
9739c0f0dcc3SMatthew G. Knepley /*@
9740c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9741c0f0dcc3SMatthew G. Knepley 
9742c0f0dcc3SMatthew G. Knepley   Input Parameter:
9743c0f0dcc3SMatthew G. Knepley - dm - The DM
9744c0f0dcc3SMatthew G. Knepley 
9745c0f0dcc3SMatthew G. Knepley   Level: developer
9746c0f0dcc3SMatthew G. Knepley 
9747c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9748c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9749c0f0dcc3SMatthew G. Knepley 
9750c0f0dcc3SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreate()
9751c0f0dcc3SMatthew G. Knepley @*/
9752c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9753c0f0dcc3SMatthew G. Knepley {
9754e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9755c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9756c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9757c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9758c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9759c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9760c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9761c0f0dcc3SMatthew G. Knepley   const char        *name;
9762e5ed2c37SJose E. Roman #endif
9763c0f0dcc3SMatthew G. Knepley 
9764c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9765c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9766c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
97679566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) dm, &name));
97689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
97699566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
97709566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
97719566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
97729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
97739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
9774c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9775c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9776c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
97779566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject) dm), "DM (%s) FE Residual Integration: %D 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)));
9778c0f0dcc3SMatthew G. Knepley #else
9779c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9780c0f0dcc3SMatthew G. Knepley #endif
9781c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9782c0f0dcc3SMatthew G. Knepley }
9783