xref: /petsc/src/dm/impls/plex/plex.c (revision dadcf80911fb48939c55327431ae8d7e47dbe367)
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;
385f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
399318fe57SMatthew G. Knepley   if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);}
405f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
69412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
70412e9a14SMatthew G. Knepley     DMPolytopeType cct;
71412e9a14SMatthew G. Knepley 
725f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellTypeLabel(dm, &ctLabel));
915f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
1055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &cdim));
1065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd));
1097e42fee7SMatthew G. Knepley   if (field >= 0) {
1105f80ce2aSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) CHKERRQ(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1115f80ce2aSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) CHKERRQ(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1127e42fee7SMatthew G. Knepley   } else {
1135f80ce2aSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) CHKERRQ(PetscSectionGetDof(section, vStart, &vcdof[0]));
1145f80ce2aSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) CHKERRQ(PetscSectionGetDof(section, cStart, &vcdof[1]));
1157e42fee7SMatthew G. Knepley   }
1165f80ce2aSJacob Faibussowitsch   CHKERRMPI(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 
1315f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldName(section, field, &fieldname));
1325f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname));
133e630c359SToby Isaac     } else {
1345f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
1685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDS(dm, &ds));
1695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSGetNumFields(ds, &Nf));
1705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSGetTotalComponents(ds, &Nl));
1715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSGetComponents(ds, &Nc));
1726913077dSMatthew G. Knepley 
1735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw));
1746913077dSMatthew G. Knepley   if (!draw) PetscFunctionReturn(0);
1755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawLGCreate(draw, n*Nl, &lg));
1766913077dSMatthew G. Knepley 
1775f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
1815f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
1875f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDSGetDiscretization(ds, f, &disc));
1886913077dSMatthew G. Knepley       /* TODO Create names for components */
1896913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
1905f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectGetName(disc, &fname));
1915f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscStrcpy(tmpname, vname));
1925f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN));
1935f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN));
1945f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscStrallocpy(tmpname, &names[l]));
1956913077dSMatthew G. Knepley       }
1966913077dSMatthew G. Knepley     }
1976913077dSMatthew G. Knepley   }
1985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawLGSetLegend(lg, (const char *const *) names));
1996913077dSMatthew G. Knepley   /* Just add P_1 support for now */
2005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates));
2025f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(coordinates, &coords));
2035f80ce2aSJacob Faibussowitsch   for (i = 0; i < n; ++i) CHKERRQ(VecGetArrayRead(u[i], &sol[i]));
2046913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2056913077dSMatthew G. Knepley     PetscScalar *x, *svals;
2066913077dSMatthew G. Knepley 
2075f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPointLocalRead(dm, v, coords, &x));
2086913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
2095f80ce2aSJacob Faibussowitsch       CHKERRQ(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     }
2125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
2136913077dSMatthew G. Knepley   }
2145f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(coordinates, &coords));
2155f80ce2aSJacob Faibussowitsch   for (i = 0; i < n; ++i) CHKERRQ(VecRestoreArrayRead(u[i], &sol[i]));
2165f80ce2aSJacob Faibussowitsch   for (l = 0; l < n*Nl; ++l) CHKERRQ(PetscFree(names[l]));
2175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree3(sol, names, vals));
2186913077dSMatthew G. Knepley 
2195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawLGDraw(lg));
2205f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
2295f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(u, &dm));
2305f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
2515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw));
2525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
2535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &dim));
2545f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(dm, &s));
2555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(s, &Nf));
2565f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoarsenLevel(dm, &level));
2575f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm, &cdm));
2585f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(cdm, &coordSection));
2595f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates));
2605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2615f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
262e412dcbdSMatthew G. Knepley 
2635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) v, &name));
2645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetOutputSequenceNumber(dm, &step, &time));
265e412dcbdSMatthew G. Knepley 
2665f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(coordinates, &N));
2675f80ce2aSJacob Faibussowitsch   CHKERRQ(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   }
2725f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(coordinates, &coords));
2735f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
2835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldComponents(s, f, &Nc));
2845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldName(s, f, &fname));
285d1df6f1dSMatthew G. Knepley 
2865f80ce2aSJacob Faibussowitsch     if (v->hdr.prefix) CHKERRQ(PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix)));
287d1df6f1dSMatthew G. Knepley     else               {prefix[0] = '\0';}
288d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
2895f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
2905f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetSubVector(v, fis, &fv));
2915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrlcat(prefix, fname,sizeof(prefix)));
2925f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
2975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerDrawGetDraw(viewer, w, &draw));
2985f80ce2aSJacob Faibussowitsch       if (Nc > 1) CHKERRQ(PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time));
2995f80ce2aSJacob Faibussowitsch       else        CHKERRQ(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time));
3005f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawSetTitle(draw, title));
301d1df6f1dSMatthew G. Knepley 
302d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3035f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
304339e3443SMatthew G. Knepley       if (!flg) {
3055f80ce2aSJacob Faibussowitsch         CHKERRQ(VecMin(fv, NULL, &vbound[0]));
3065f80ce2aSJacob Faibussowitsch         CHKERRQ(VecMax(fv, NULL, &vbound[1]));
307d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
308339e3443SMatthew G. Knepley       }
3095f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawGetPopup(draw, &popup));
3105f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
3115f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]));
312e412dcbdSMatthew G. Knepley 
3135f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
3185f80ce2aSJacob Faibussowitsch         CHKERRQ(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 
3265f80ce2aSJacob Faibussowitsch           CHKERRQ(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           }
3395f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
340339e3443SMatthew G. Knepley         }
3415f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
342e412dcbdSMatthew G. Knepley         switch (numCoords) {
343e412dcbdSMatthew G. Knepley         case 6:
3449edc3542SMatthew Knepley         case 12: /* Localized triangle */
3455f80ce2aSJacob Faibussowitsch           CHKERRQ(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 */
3495f80ce2aSJacob Faibussowitsch           CHKERRQ(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]));
3505f80ce2aSJacob Faibussowitsch           CHKERRQ(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         }
3545f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
355e412dcbdSMatthew G. Knepley       }
3565f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(fv, &array));
3575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawFlush(draw));
3585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawPause(draw));
3595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawSave(draw));
360d1df6f1dSMatthew G. Knepley     }
361d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3625f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreSubVector(v, fis, &fv));
3635f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&fis));
3645f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
3785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw));
3795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawIsNull(draw, &isnull));
3806913077dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
3816913077dSMatthew G. Knepley 
3825f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
3835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &dim));
3846913077dSMatthew G. Knepley   switch (dim) {
3855f80ce2aSJacob Faibussowitsch   case 1: CHKERRQ(VecView_Plex_Local_Draw_1D(v, viewer));break;
3865f80ce2aSJacob Faibussowitsch   case 2: CHKERRQ(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;
4035f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
4045f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) v, &name));
4065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) locv, name));
4075f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCopy(v, locv));
4085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(dm, &section));
4095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
410e630c359SToby Isaac   if (!numFields) {
4115f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4125f80ce2aSJacob Faibussowitsch     CHKERRQ(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++) {
4175f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
418e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)locv));
4205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv));
421e630c359SToby Isaac     }
4225f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
4335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
43428b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk));
4365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5));
4375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,  &isdraw));
4385f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
4485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetNumFields(dm, &numFields));
449684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
4505f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
4565f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLocalVector(dm, &locv));
4575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetName((PetscObject) v, &name));
4585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectSetName((PetscObject) locv, name));
4595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
4605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
4615f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCopy(v, locv));
4625f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetOutputSequenceNumber(dm, NULL, &time));
4635f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
464ef31f671SMatthew G. Knepley     }
465552f7358SJed Brown     if (isvtk) {
4665f80ce2aSJacob Faibussowitsch       CHKERRQ(VecView_Plex_Local_VTK(locv, viewer));
467b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
468b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4695f80ce2aSJacob Faibussowitsch       CHKERRQ(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) {
4745f80ce2aSJacob Faibussowitsch       CHKERRQ(VecView_Plex_Local_Draw(locv, viewer));
475684b87d9SLisandro Dalcin     } else if (isglvis) {
4765f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetOutputSequenceNumber(dm, &step, NULL));
4775f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerGLVisSetSnapId(viewer, step));
4785f80ce2aSJacob Faibussowitsch       CHKERRQ(VecView_GLVis(locv, viewer));
479684b87d9SLisandro Dalcin     }
480798534f6SMatthew G. Knepley     if (fem) {
4815f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
4825f80ce2aSJacob Faibussowitsch       CHKERRQ(DMRestoreLocalVector(dm, &locv));
483798534f6SMatthew G. Knepley     }
484552f7358SJed Brown   } else {
485684b87d9SLisandro Dalcin     PetscBool isseq;
486684b87d9SLisandro Dalcin 
4875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
4885f80ce2aSJacob Faibussowitsch     if (isseq) CHKERRQ(VecView_Seq(v, viewer));
4895f80ce2aSJacob Faibussowitsch     else       CHKERRQ(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;
5005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
50128b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
5035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
5045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
5055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
5065f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
5125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalVector(dm, &locv));
5135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) v, &name));
5145f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) locv, name));
5155f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5165f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5175f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
5185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
5195f80ce2aSJacob Faibussowitsch     CHKERRQ(VecView_Plex_Local(locv, viewer));
5205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
5215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreLocalVector(dm, &locv));
522b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
523b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5245f80ce2aSJacob Faibussowitsch     CHKERRQ(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)
5305f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
5375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5385f80ce2aSJacob Faibussowitsch     if (isseq) CHKERRQ(VecView_Seq(v, viewer));
5395f80ce2aSJacob Faibussowitsch     else       CHKERRQ(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;
5535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(originalv, &dm));
5545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) originalv, &comm));
55528b400f6SJacob Faibussowitsch   PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetFormat(viewer, &format));
5575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
5585f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
5675f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetLocalSize(originalv, &n));
5685f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
569d930f514SMatthew G. Knepley         if (n == nroots) {
5705f80ce2aSJacob Faibussowitsch           CHKERRQ(DMGetGlobalVector(dm, &v));
5715f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5725f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5735f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscObjectGetName((PetscObject) originalv, &vecname));
5745f80ce2aSJacob Faibussowitsch           CHKERRQ(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)
5825f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
5915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5925f80ce2aSJacob Faibussowitsch     if (isseq) CHKERRQ(VecView_Seq(v, viewer));
5935f80ce2aSJacob Faibussowitsch     else       CHKERRQ(VecView_MPI(v, viewer));
594d930f514SMatthew G. Knepley   }
5955f80ce2aSJacob Faibussowitsch   if (v != originalv) CHKERRQ(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;
6055f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
60628b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6075f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
6135f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetOutputDM(dm, &dmBC));
6145f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalVector(dmBC, &gv));
6155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) v, &name));
6165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject) gv, name));
6175f80ce2aSJacob Faibussowitsch     CHKERRQ(VecLoad_Default(gv, viewer));
6185f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreGlobalVector(dmBC, &gv));
6212c40f234SMatthew G. Knepley   } else {
6225f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
6335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
63428b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
6365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
6372c40f234SMatthew G. Knepley   if (ishdf5) {
638878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6395f80ce2aSJacob Faibussowitsch     CHKERRQ(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)
6455f80ce2aSJacob Faibussowitsch     CHKERRQ(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 {
6505f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
6625f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(originalv, &dm));
66328b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetFormat(viewer, &format));
6655f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
6745f80ce2aSJacob Faibussowitsch           CHKERRQ(DMGetGlobalVector(dm, &v));
6755f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscObjectGetName((PetscObject) originalv, &vecname));
6765f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscObjectSetName((PetscObject) v, vecname));
6775f80ce2aSJacob Faibussowitsch           CHKERRQ(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6785f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexNaturalToGlobalBegin(dm, v, originalv));
6795f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexNaturalToGlobalEnd(dm, v, originalv));
6805f80ce2aSJacob Faibussowitsch           CHKERRQ(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 {
6875f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
7035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
7045f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates));
7055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
7065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &depthLabel));
7075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7105f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
7195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetValue(celltypeLabel, c, &ct));
7205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]));
7215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7225f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
7275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(coordSection, point, &dof));
728731e8ddeSMatthew G. Knepley       if (!dof) continue;
7295f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValue(depthLabel, point, &depth));
7305f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(coordSection, point, &off));
7315f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point));
732731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
7335f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, " ("));
734731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7355f80ce2aSJacob Faibussowitsch           if (d > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", "));
7365f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d])));
737731e8ddeSMatthew G. Knepley         }
7385f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, ")"));
739731e8ddeSMatthew G. Knepley       }
7405f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n"));
741731e8ddeSMatthew G. Knepley     }
7425f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPopTab(viewer));
744731e8ddeSMatthew G. Knepley   }
7455f80ce2aSJacob Faibussowitsch   CHKERRQ(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) {
7585f80ce2aSJacob Faibussowitsch     for (i = 0; i < dim; ++i) CHKERRQ(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     }
7835f80ce2aSJacob Faibussowitsch     for (i = 0; i < dim; ++i) CHKERRQ(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;
7975f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm, &cdm));
7985f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(cdm, &coordSection));
7995f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates));
8005f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
8075f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8085f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) dm, &name));
8105f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
8115f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &dim));
8135f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight));
8145f80ce2aSJacob Faibussowitsch     if (name) CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
8155f80ce2aSJacob Faibussowitsch     else      CHKERRQ(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s"));
8165f80ce2aSJacob Faibussowitsch     if (cellHeight) CHKERRQ(PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight));
8175f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "Supports:\n", name));
8185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPushSynchronized(viewer));
8195f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
8235f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof));
8245f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off));
825552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
8265f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]));
827552f7358SJed Brown       }
828552f7358SJed Brown     }
8295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(viewer));
8305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "Cones:\n", name));
8315f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
8355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
8365f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
837552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
8385f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
839552f7358SJed Brown       }
840552f7358SJed Brown     }
8415f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(viewer));
8425f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
8505f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL));
8515f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetNumFields(coordSection, &Nf));
8532c71b3e2SJacob Faibussowitsch       PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf);
8545f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8555f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8565f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectGetName((PetscObject) coordinates, &name));
8575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf));
8585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "  field 0 with %D components\n", Nc));
8595f80ce2aSJacob Faibussowitsch       if (cs != CS_CARTESIAN) CHKERRQ(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
86019ad8254SMatthew G. Knepley 
8615f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(coordinates, &array));
8625f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushSynchronized(viewer));
8635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
86419ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
86519ad8254SMatthew G. Knepley         PetscInt dof, off;
86619ad8254SMatthew G. Knepley 
8675f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(coordSection, p, &dof));
8685f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(coordSection, p, &off));
8695f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4D) dim %2D offset %3D", p, dof, off));
8705f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
8715f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
87219ad8254SMatthew G. Knepley       }
8735f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerFlush(viewer));
8745f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
8755f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(coordinates, &array));
8763d2e540fSStefano Zampini     }
8775f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetNumLabels(dm, &numLabels));
8785f80ce2aSJacob Faibussowitsch     if (numLabels) CHKERRQ(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 
8845f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabelName(dm, l, &name));
8855f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrcmp(name, "depth", &isdepth));
8869318fe57SMatthew G. Knepley       if (isdepth) continue;
8875f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(dm, name, &label));
8885f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelView(label, viewer));
8899318fe57SMatthew G. Knepley     }
890552f7358SJed Brown     if (size > 1) {
891552f7358SJed Brown       PetscSF sf;
892552f7358SJed Brown 
8935f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetPointSF(dm, &sf));
8945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFView(sf, viewer));
895552f7358SJed Brown     }
8965f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
9145f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &dim));
9155f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepth(dm, &depth));
9165f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetNumLabels(dm, &numLabels));
9170588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9180588280cSMatthew G. Knepley     numColors  = 10;
9190588280cSMatthew G. Knepley     numLColors = 10;
9205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9235f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
9275f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
9295f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
9315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9320588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9340588280cSMatthew G. Knepley     if (!useColors) {
9350588280cSMatthew G. Knepley       numColors = 3;
9365f80ce2aSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) CHKERRQ(PetscStrallocpy(defcolors[c], &colors[c]));
9370588280cSMatthew G. Knepley     }
9385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9390588280cSMatthew G. Knepley     if (!useColors) {
9400588280cSMatthew G. Knepley       numLColors = 4;
9415f80ce2aSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) CHKERRQ(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9420588280cSMatthew G. Knepley     }
9435f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
9455f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
9485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
949fe1cc32dSStefano Zampini 
950fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
9515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
9525f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9535f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9545f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
955fe1cc32dSStefano Zampini     if (lflg) {
956fe1cc32dSStefano Zampini       DMLabel lbl;
957fe1cc32dSStefano Zampini 
9585f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(dm, lname, &lbl));
959fe1cc32dSStefano Zampini       if (lbl) {
960fe1cc32dSStefano Zampini         PetscInt val, defval;
961fe1cc32dSStefano Zampini 
9625f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelGetDefaultValue(lbl, &defval));
9635f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscBTCreate(pEnd-pStart, &wp));
964fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
965fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
966fe1cc32dSStefano Zampini           PetscInt  closureSize;
967fe1cc32dSStefano Zampini 
9685f80ce2aSJacob Faibussowitsch           CHKERRQ(DMLabelGetValue(lbl, c, &val));
969fe1cc32dSStefano Zampini           if (val == defval) continue;
970fe1cc32dSStefano Zampini 
9715f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
972fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
9735f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscBTSet(wp, closure[p] - pStart));
974fe1cc32dSStefano Zampini           }
9755f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
976fe1cc32dSStefano Zampini         }
977fe1cc32dSStefano Zampini       }
978fe1cc32dSStefano Zampini     }
979fe1cc32dSStefano Zampini 
9805f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9815f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) dm, &name));
9835f80ce2aSJacob Faibussowitsch     CHKERRQ(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) {
9905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
991770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
992770b213bSMatthew G Knepley         if (p > 0 && p == size-1) {
9935f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p));
994770b213bSMatthew G Knepley         } else if (p > 0) {
9955f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p));
996770b213bSMatthew G Knepley         }
9975f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p));
998770b213bSMatthew G Knepley       }
9995f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
10045f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart));
10055f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1));
10065f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart));
10075f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.));
10085f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart));
10095f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1));
10105f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.));
10115f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart));
10125f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart));
10135f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1));
10145f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart));
10155f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.));
1016b7f6ffafSMatthew G. Knepley     }
10175f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale));
1018fe1cc32dSStefano Zampini 
1019552f7358SJed Brown     /* Plot vertices */
10205f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(coordinates, &coords));
10215f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
10275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(coordSection, v, &dof));
10285f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(coordSection, v, &off));
10295f80ce2aSJacob Faibussowitsch       CHKERRQ(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) {
10385f80ce2aSJacob Faibussowitsch         if (d > 0) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10395f80ce2aSJacob Faibussowitsch         CHKERRQ(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;
10455f80ce2aSJacob Faibussowitsch         CHKERRQ(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]) {
10495f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v));
1050b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
10515f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
1052b7f6ffafSMatthew G. Knepley       } else {
10535f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank));
10540588280cSMatthew G. Knepley       }
1055552f7358SJed Brown     }
10565f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(coordinates, &coords));
10575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(viewer));
1058b7f6ffafSMatthew G. Knepley     /* Plot edges */
1059b7f6ffafSMatthew G. Knepley     if (plotEdges) {
10605f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(coordinates, &coords));
10615f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
10675f80ce2aSJacob Faibussowitsch         CHKERRQ(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);
10695f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, e, &cone));
10705f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(coordSection, cone[0], &dof));
10715f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(coordSection, cone[0], &offA));
10725f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(coordSection, cone[1], &offB));
10735f80ce2aSJacob Faibussowitsch         CHKERRQ(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) {
10815f80ce2aSJacob Faibussowitsch           if (d > 0) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10825f80ce2aSJacob Faibussowitsch           CHKERRQ(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;
10885f80ce2aSJacob Faibussowitsch           CHKERRQ(DMGetLabelValue(dm, names[l], v, &val));
1089b7f6ffafSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1090b7f6ffafSMatthew G. Knepley         }
10915f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e));
1092b7f6ffafSMatthew G. Knepley       }
10935f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(coordinates, &coords));
10945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerFlush(viewer));
10955f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
11065f80ce2aSJacob Faibussowitsch           CHKERRQ(DMGetLabelValue(dm, names[l], e, &val));
1107846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1108846a3e8bSMatthew G. Knepley         }
11095f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, e, &cone));
11105f80ce2aSJacob Faibussowitsch         CHKERRQ(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;
11185f80ce2aSJacob Faibussowitsch         CHKERRQ(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 
11255f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetCone(dm, c, &cone));
11265f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize));
1127b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1128b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1129b7f6ffafSMatthew G. Knepley 
11305f80ce2aSJacob Faibussowitsch             CHKERRQ(DMPlexGetCone(dm, cone[e], &econe));
11315f80ce2aSJacob Faibussowitsch             CHKERRQ(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 
11375f80ce2aSJacob Faibussowitsch           CHKERRQ(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           }
11435f80ce2aSJacob Faibussowitsch           CHKERRQ(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;
11535f80ce2aSJacob Faibussowitsch                 CHKERRQ(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]);
11555f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank));
11565f80ce2aSJacob Faibussowitsch                 CHKERRQ(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
1157b7f6ffafSMatthew G. Knepley               } else {
11585f80ce2aSJacob Faibussowitsch                 CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1159b7f6ffafSMatthew G. Knepley               }
1160b7f6ffafSMatthew G. Knepley             }
11615f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank));
1162b7f6ffafSMatthew G. Knepley           }
11635f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
11645f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1165846a3e8bSMatthew G. Knepley         }
1166846a3e8bSMatthew G. Knepley       }
1167b7f6ffafSMatthew G. Knepley     }
11685f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
11765f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
11775f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
11835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(coordSection, point, &dof));
11845f80ce2aSJacob Faibussowitsch         CHKERRQ(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;}
11955f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1196846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11975f80ce2aSJacob Faibussowitsch         if (d > 0) CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11985f80ce2aSJacob Faibussowitsch         CHKERRQ(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;
12045f80ce2aSJacob Faibussowitsch         CHKERRQ(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]) {
12085f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c));
1209b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
12105f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
1211b7f6ffafSMatthew G. Knepley       } else {
12125f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank));
1213846a3e8bSMatthew G. Knepley       }
1214846a3e8bSMatthew G. Knepley     }
12155f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(coordinates, &coords));
1216b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1217b7f6ffafSMatthew G. Knepley       color = colors[depth%numColors];
12185f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\n"));
12215f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12225f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "}\n"));
1223552f7358SJed Brown 
1224b7f6ffafSMatthew G. Knepley       color = colors[1%numColors];
12255f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12265f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\n"));
12285f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12295f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "}\n"));
1230b7f6ffafSMatthew G. Knepley 
1231b7f6ffafSMatthew G. Knepley       color = colors[0%numColors];
12325f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12345f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "{\n"));
12355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12365f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
12425f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, p, &cone));
12435f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
1244b7f6ffafSMatthew G. Knepley         for (cp = 0; cp < coneSize; ++cp) {
12455f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank));
1246552f7358SJed Brown         }
12470588280cSMatthew G. Knepley       }
12480588280cSMatthew G. Knepley     }
12495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(viewer));
12505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
12515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
12525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name));
12535f80ce2aSJacob Faibussowitsch     for (l = 0; l < numLabels;  ++l) CHKERRQ(PetscFree(names[l]));
12545f80ce2aSJacob Faibussowitsch     for (c = 0; c < numColors;  ++c) CHKERRQ(PetscFree(colors[c]));
12555f80ce2aSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) CHKERRQ(PetscFree(lcolors[c]));
12565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(names, colors, lcolors));
12575f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
12725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
12735f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(comm,&rank));
1274b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
12755f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm));
12760f7d6e4aSStefano Zampini #endif
12770f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
12785f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_group(comm,&ggroup));
12795f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_group(ncomm,&ngroup));
12800f7d6e4aSStefano Zampini       d1   = 0;
12815f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2));
12820f7d6e4aSStefano Zampini       nid  = d2;
12835f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_free(&ggroup));
12845f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_free(&ngroup));
12855f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_free(&ncomm));
12860f7d6e4aSStefano Zampini     } else nid = 0.0;
12870f7d6e4aSStefano Zampini 
12880f7d6e4aSStefano Zampini     /* Get connectivity */
12895f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetVTKCellHeight(dm,&cellHeight));
12905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid));
12910f7d6e4aSStefano Zampini 
12920f7d6e4aSStefano Zampini     /* filter overlapped local cells */
12935f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd));
12945f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(gid,&idxs));
12955f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(gid,&cum));
12965f80ce2aSJacob Faibussowitsch     CHKERRQ(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     }
13015f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(gid,&idxs));
13022c71b3e2SJacob Faibussowitsch     PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum);
13035f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&gid));
13045f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid));
13050f7d6e4aSStefano Zampini 
13060f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13075f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis));
13085f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown));
13095f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown));
13105f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(cown,&array));
13110f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13125f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(cown,&array));
13135f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterCreate(cown,acis,acown,NULL,&sct));
13145f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13155f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13165f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&acis));
13175f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterDestroy(&sct));
13185f80ce2aSJacob Faibussowitsch     CHKERRQ(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]);
13225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(cum,&work));
13235f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(gid,&g2l));
13245f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH));
13255f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&gid));
13265f80ce2aSJacob Faibussowitsch     CHKERRQ(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];
13315f80ce2aSJacob Faibussowitsch       CHKERRQ(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     }
13395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(work));
13405f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(acown,&array));
13410f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
13420f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13435f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm));
13445f80ce2aSJacob Faibussowitsch     CHKERRQ(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 */
13485f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm));
13495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]));
1350b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
13515f80ce2aSJacob Faibussowitsch     CHKERRQ(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
13535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0));
13540f7d6e4aSStefano Zampini #endif
13555f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&g2l));
13565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(start));
13575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(adjacency));
13585f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
13695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
13705f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_size(comm, &size));
13715f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(comm, &rank));
13725f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &dim));
13735f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight));
13745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) dm, &name));
13755f80ce2aSJacob Faibussowitsch     if (name) CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
13765f80ce2aSJacob Faibussowitsch     else      CHKERRQ(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s"));
13775f80ce2aSJacob Faibussowitsch     if (cellHeight) CHKERRQ(PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight));
13785f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepth(dm, &locDepth));
13795f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
13805f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1381d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
13825f80ce2aSJacob Faibussowitsch     if (size < maxSize) CHKERRQ(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
13835f80ce2aSJacob Faibussowitsch     else                CHKERRQ(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 
13875f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
13885f80ce2aSJacob Faibussowitsch       if (pStart < pEnd) CHKERRQ(DMPlexGetCellType(dm, pStart, &ct0));
1389412e9a14SMatthew G. Knepley       ict  = ct0;
13905f80ce2aSJacob Faibussowitsch       CHKERRMPI(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 
13955f80ce2aSJacob Faibussowitsch         CHKERRQ(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) {
14005f80ce2aSJacob Faibussowitsch         CHKERRMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm));
14015f80ce2aSJacob Faibussowitsch         CHKERRMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14025f80ce2aSJacob Faibussowitsch         if (d == depth) CHKERRMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
14035f80ce2aSJacob Faibussowitsch         CHKERRQ(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) {
14065f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]));
14075f80ce2aSJacob Faibussowitsch             if (hybsizes[p]   > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]));
14085f80ce2aSJacob Faibussowitsch             if (ghostsizes[p] > 0) CHKERRQ(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];
14155f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
1416ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1];
14175f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1418ca7bf7eeSMatthew G. Knepley         if (d == depth) {
1419ca7bf7eeSMatthew G. Knepley           locMinMax[0] = gcNum; locMinMax[1] = gcNum;
14205f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1421ca7bf7eeSMatthew G. Knepley         }
14225f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "  Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d));
14235f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14245f80ce2aSJacob Faibussowitsch         if (hybsizes[0]   > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14255f80ce2aSJacob Faibussowitsch         if (ghostsizes[0] > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1426ca7bf7eeSMatthew G. Knepley       }
14275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n"));
1428552f7358SJed Brown     }
14295f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
14365f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetPeriodicity(dm, &per, &maxCell, &L, &bd));
14375f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinatesLocalized(dm, &localized));
14389318fe57SMatthew G. Knepley       if (per) {
14395f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "Periodic mesh ("));
14405f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14419318fe57SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
14425f80ce2aSJacob Faibussowitsch           if (bd && d > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", "));
14435f80ce2aSJacob Faibussowitsch           if (bd)    CHKERRQ(PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]));
14449318fe57SMatthew G. Knepley         }
14455f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized"));
14465f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14479318fe57SMatthew G. Knepley       }
14489318fe57SMatthew G. Knepley     }
14495f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetNumLabels(dm, &numLabels));
14505f80ce2aSJacob Faibussowitsch     if (numLabels) CHKERRQ(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 
14585f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabelName(dm, l, &name));
14595f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(dm, name, &label));
14605f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetNumValues(label, &numValues));
14615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, "  %s: %D strata with value/size (", name, numValues));
14625f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValueIS(label, &valueIS));
14635f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(valueIS, &values));
14645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1465a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1466a57dd577SMatthew G Knepley         PetscInt size;
1467a57dd577SMatthew G Knepley 
14685f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelGetStratumSize(label, values[v], &size));
14695f80ce2aSJacob Faibussowitsch         if (v > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", "));
14705f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size));
1471a57dd577SMatthew G Knepley       }
14725f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, ")\n"));
14735f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14745f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(valueIS, &values));
14755f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
14825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(Nl, &labelNames));
14835f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
14875f80ce2aSJacob Faibussowitsch         CHKERRQ(DMHasLabel(dm, labelNames[l], &flg));
1488c1cad2e7SMatthew G. Knepley         if (flg) {
14895f80ce2aSJacob Faibussowitsch           CHKERRQ(DMGetLabel(dm, labelNames[l], &label));
14905f80ce2aSJacob Faibussowitsch           CHKERRQ(DMLabelView(label, viewer));
1491c1cad2e7SMatthew G. Knepley         }
14925f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(labelNames[l]));
1493c1cad2e7SMatthew G. Knepley       }
14945f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
15035f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectGetName(dm->fields[f].disc, &name));
15045f80ce2aSJacob Faibussowitsch         if (numLabels) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15055f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPushTab(viewer));
15065f80ce2aSJacob Faibussowitsch         if (dm->fields[f].label) CHKERRQ(DMLabelView(dm->fields[f].label, viewer));
150734aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15085f80ce2aSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15095f80ce2aSJacob Faibussowitsch           else                            CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
151034aa8a36SMatthew G. Knepley         } else {
15115f80ce2aSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15125f80ce2aSJacob Faibussowitsch           else                            CHKERRQ(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
151334aa8a36SMatthew G. Knepley         }
15145f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPopTab(viewer));
151534aa8a36SMatthew G. Knepley       }
151634aa8a36SMatthew G. Knepley     }
15175f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoarseDM(dm, &cdm));
15188e7ff633SMatthew G. Knepley     if (cdm) {
15195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushTab(viewer));
15205f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexView_Ascii(cdm, viewer));
15215f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
15345f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
15355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dm, cell, &ct));
15365f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
15465f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), y,    PetscRealPart(coords[1]), y,    PETSC_DRAW_BLACK));
15475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK));
15485f80ce2aSJacob Faibussowitsch       CHKERRQ(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 
15575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15585f80ce2aSJacob Faibussowitsch       CHKERRQ(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));
15595f80ce2aSJacob Faibussowitsch       CHKERRQ(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:
15665f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
15705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15725f80ce2aSJacob Faibussowitsch     CHKERRQ(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:
15755f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
15795f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
15835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
15865f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
16015f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
16025f80ce2aSJacob Faibussowitsch   CHKERRQ(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         }
16175f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords));
1618e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
16195f80ce2aSJacob Faibussowitsch           CHKERRQ(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));
16205f80ce2aSJacob Faibussowitsch           CHKERRQ(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;
16435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &dim));
16442c71b3e2SJacob Faibussowitsch   PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim);
16455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
16465f80ce2aSJacob Faibussowitsch   if (!drawAffine) CHKERRQ(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords));
16475f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm, &cdm));
16485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(cdm, &coordSection));
16495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates));
16505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1652e412dcbdSMatthew G. Knepley 
16535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDrawGetDraw(viewer, 0, &draw));
16545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawIsNull(draw, &isnull));
1655e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
16565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawSetTitle(draw, "Mesh"));
1657e412dcbdSMatthew G. Knepley 
16585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(coordinates, &N));
16595f80ce2aSJacob Faibussowitsch   CHKERRQ(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   }
16645f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(coordinates, &coords));
16655f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm)));
16665f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm)));
16675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
16685f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
16745f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
1675e5c487bfSMatthew G. Knepley     if (drawAffine) {
16765f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexDrawCell(dm, draw, c, coords));
1677e5c487bfSMatthew G. Knepley     } else {
16785f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1679cf3064d3SMatthew G. Knepley     }
16805f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1681cf3064d3SMatthew G. Knepley   }
16825f80ce2aSJacob Faibussowitsch   if (!drawAffine) CHKERRQ(PetscFree2(refCoords, edgeCoords));
16835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawFlush(draw));
16845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawPause(draw));
16855f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
17025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii));
17035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
17045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
17055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
17065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
17075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus));
1708552f7358SJed Brown   if (iascii) {
17098135c375SStefano Zampini     PetscViewerFormat format;
17105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
17118135c375SStefano Zampini     if (format == PETSC_VIEWER_ASCII_GLVIS) {
17125f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexView_GLVis(dm, viewer));
17138135c375SStefano Zampini     } else {
17145f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexView_Ascii(dm, viewer));
17158135c375SStefano Zampini     }
1716c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1717c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17185f80ce2aSJacob Faibussowitsch     CHKERRQ(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) {
17235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVTKWriteAll((PetscObject) dm,viewer));
1724e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexView_Draw(dm, viewer));
17268135c375SStefano Zampini   } else if (isglvis) {
17275f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
17385f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLabelSize(dm,"Cell Sets",&numCS));
17396823f3c5SBlaise Bourdin     if (!numCS) {
17401e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17415f80ce2aSJacob Faibussowitsch       CHKERRQ(DMCreateLabel(dm, "Cell Sets"));
17425f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17435f80ce2aSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) CHKERRQ(DMSetLabelValue(dm, "Cell Sets", c, 1));
17446823f3c5SBlaise Bourdin     }
17455f80ce2aSJacob Faibussowitsch     CHKERRQ(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 */
17515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg));
1752cb3ba0daSMatthew G. Knepley   if (flg) {
1753cb3ba0daSMatthew G. Knepley     Vec ranks;
17545f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateRankField(dm, &ranks));
17555f80ce2aSJacob Faibussowitsch     CHKERRQ(VecView(ranks, viewer));
17565f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&ranks));
1757cb3ba0daSMatthew G. Knepley   }
1758002a2709SMatthew G. Knepley   /* Optionally view a label */
17595f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
17645f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
17665f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateLabelField(dm, label, &val));
17675f80ce2aSJacob Faibussowitsch     CHKERRQ(VecView(val, viewer));
17685f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
17935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
17945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0));
17957f96f51bSksagiyam   if (ishdf5) {
17967f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
17977f96f51bSksagiyam     PetscViewerFormat format;
17985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
17997f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18007f96f51bSksagiyam       IS globalPointNumbering;
18017f96f51bSksagiyam 
18025f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18035f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18045f80ce2aSJacob Faibussowitsch       CHKERRQ(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   }
18105f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
18345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0));
183677b8e257Sksagiyam   if (ishdf5) {
183777b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
183877b8e257Sksagiyam     PetscViewerFormat format;
18395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
184077b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18415f80ce2aSJacob Faibussowitsch       CHKERRQ(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   }
18475f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
18715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0));
1873bd6565f1Sksagiyam   if (ishdf5) {
1874bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1875bd6565f1Sksagiyam     IS                globalPointNumbering;
1876bd6565f1Sksagiyam     PetscViewerFormat format;
1877bd6565f1Sksagiyam 
18785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
1879bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18805f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18815f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
18825f80ce2aSJacob Faibussowitsch       CHKERRQ(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   }
18885f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
19195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
19205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0));
1921021affd3Sksagiyam   if (ishdf5) {
1922021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19235f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
19285f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
19865f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(vec, &m1));
19875f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(sectiondm, &section));
19885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints));
19895f80ce2aSJacob Faibussowitsch     if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m));
19905f80ce2aSJacob Faibussowitsch     else CHKERRQ(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   }
19935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0));
19953e97647fSksagiyam   if (ishdf5) {
19963e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
19975f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
20025f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
20595f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(vec, &m1));
20605f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(sectiondm, &section));
20615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20625f80ce2aSJacob Faibussowitsch     if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m));
20635f80ce2aSJacob Faibussowitsch     else CHKERRQ(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   }
20665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0));
20683e97647fSksagiyam   if (ishdf5) {
20693e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20705f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
20755f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
20865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5));
2087d4f5a9a0SVaclav Hapla   if (ishdf5) {
20882c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
20899c48423bSVaclav Hapla     PetscViewerFormat format;
20905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
20919c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
20925f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2093509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20945f80ce2aSJacob Faibussowitsch       CHKERRQ(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);
21275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0));
2129ea8e1828Sksagiyam   if (ishdf5) {
2130ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2131ea8e1828Sksagiyam     PetscViewerFormat format;
21325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
2133ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21345f80ce2aSJacob Faibussowitsch       CHKERRQ(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   }
21405f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
21665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21683e701f1cSksagiyam   if (ishdf5) {
21693e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
21703e701f1cSksagiyam     PetscViewerFormat format;
21715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
21723e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21735f80ce2aSJacob Faibussowitsch       CHKERRQ(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   }
21795f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
22085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
22095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0));
2210b08ad5deSksagiyam   if (ishdf5) {
2211b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2212b08ad5deSksagiyam     PetscViewerFormat format;
2213b08ad5deSksagiyam 
22145f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer, &format));
2215b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22165f80ce2aSJacob Faibussowitsch       CHKERRQ(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   }
22225f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
22855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
22865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0));
2287f84dd6b4Sksagiyam   if (ishdf5) {
2288f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
22895f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
22945f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
23505f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(vec, &m1));
23515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(sectiondm, &section));
23525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints));
23535f80ce2aSJacob Faibussowitsch     if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m));
23545f80ce2aSJacob Faibussowitsch     else CHKERRQ(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   }
23575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
23585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23598be3dfe1Sksagiyam   if (ishdf5) {
23608be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
23615f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
23665f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
24225f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(vec, &m1));
24235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(sectiondm, &section));
24245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24255f80ce2aSJacob Faibussowitsch     if (includesConstraints) CHKERRQ(PetscSectionGetStorageSize(section, &m));
24265f80ce2aSJacob Faibussowitsch     else CHKERRQ(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   }
24295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
24305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24318be3dfe1Sksagiyam   if (ishdf5) {
24328be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24335f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
24385f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
24475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL));
24485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL));
24495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL));
24505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL));
24510d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
24525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&mesh->coneSection));
24535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->cones));
24545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->coneOrientations));
24555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&mesh->supportSection));
24565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&mesh->subdomainSection));
24575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->supports));
24585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->facesTmp));
24595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->tetgenOpts));
24605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->triangleOpts));
24615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->transformType));
24625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPartitionerDestroy(&mesh->partitioner));
24635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelDestroy(&mesh->subpointMap));
24645f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&mesh->subpointIS));
24655f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&mesh->globalVertexNumbers));
24665f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&mesh->globalCellNumbers));
24675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&mesh->anchorSection));
24685f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&mesh->anchorIS));
24695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&mesh->parentSection));
24705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->parents));
24715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->childIDs));
24725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&mesh->childSection));
24735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->children));
24745f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&mesh->referenceTree));
24755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscGridHashDestroy(&mesh->lbox));
24765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mesh->neighbors));
24775f80ce2aSJacob Faibussowitsch   if (mesh->metricCtx) CHKERRQ(PetscFree(mesh->metricCtx));
2478552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
24795f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
24935f80ce2aSJacob Faibussowitsch   CHKERRQ(MatInitializePackage());
2494b412c318SBarry Smith   mtype = dm->mattype;
24955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalSection(dm, &sectionGlobal));
24965f80ce2aSJacob Faibussowitsch   /* CHKERRQ(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
24975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
24985f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PetscObjectComm((PetscObject)dm), J));
24995f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25005f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*J, mtype));
25015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetFromOptions(*J));
25025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(*J, &mbs));
2503acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATSHELL, &isShell));
25055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25115f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
25175f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalToGlobalMapping(dm,&ltog));
25185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2519e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2520a9d99c84SMatthew G. Knepley       PetscInt bdof;
2521a9d99c84SMatthew G. Knepley 
25225f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(sectionGlobal, p, &dof));
25235f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
25345f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
25385f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetLocalToGlobalMapping(*J,ltog,ltog));
25390682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
25405f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetBlockSize(*J, bs));
25415f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetUp(*J));
25420682b8bbSJed Brown     } else {
25435f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu));
25445f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
25455f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree4(dnz, onz, dnzu, onzu));
2546552f7358SJed Brown     }
2547aa0f6e3cSJed Brown   }
25485f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
25775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(PETSC_COMM_SELF,&sf));
25785f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(dm,&section));
25795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection));
25805f80ce2aSJacob Faibussowitsch     CHKERRQ(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);
26085f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
26345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
26355f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
2661*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
26625f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
26915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetDof(mesh->coneSection, p, size));
26920d644c17SKarl Rupp 
2693552f7358SJed Brown   mesh->maxConeSize = PetscMax(mesh->maxConeSize, size);
2694552f7358SJed Brown   PetscFunctionReturn(0);
2695552f7358SJed Brown }
2696552f7358SJed Brown 
2697f5a469b9SMatthew G. Knepley /*@
2698eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2699f5a469b9SMatthew G. Knepley 
2700f5a469b9SMatthew G. Knepley   Not collective
2701f5a469b9SMatthew G. Knepley 
2702f5a469b9SMatthew G. Knepley   Input Parameters:
2703f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2704eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2705f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2706f5a469b9SMatthew G. Knepley 
2707f5a469b9SMatthew G. Knepley   Output Parameter:
2708f5a469b9SMatthew G. Knepley 
2709f5a469b9SMatthew G. Knepley   Note:
2710f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2711f5a469b9SMatthew G. Knepley 
2712f5a469b9SMatthew G. Knepley   Level: beginner
2713f5a469b9SMatthew G. Knepley 
2714f5a469b9SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart()
2715f5a469b9SMatthew G. Knepley @*/
2716f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2717f5a469b9SMatthew G. Knepley {
2718f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2719f5a469b9SMatthew G. Knepley   PetscInt       csize;
2720f5a469b9SMatthew G. Knepley 
2721f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2722f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionAddDof(mesh->coneSection, p, size));
27245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &csize));
2725f5a469b9SMatthew G. Knepley 
2726f5a469b9SMatthew G. Knepley   mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize);
2727f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2728f5a469b9SMatthew G. Knepley }
2729f5a469b9SMatthew G. Knepley 
2730552f7358SJed Brown /*@C
2731eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2732552f7358SJed Brown 
2733552f7358SJed Brown   Not collective
2734552f7358SJed Brown 
2735552f7358SJed Brown   Input Parameters:
2736833c876bSVaclav Hapla + dm - The DMPlex
2737eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2738552f7358SJed Brown 
2739552f7358SJed Brown   Output Parameter:
2740552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2741552f7358SJed Brown 
2742552f7358SJed Brown   Level: beginner
2743552f7358SJed Brown 
27443813dfbdSMatthew G Knepley   Fortran Notes:
27453813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27463813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2747922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2748922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
27493813dfbdSMatthew G Knepley 
2750e45f02b0SMatthew G. Knepley .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart()
2751552f7358SJed Brown @*/
2752552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2753552f7358SJed Brown {
2754552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2755552f7358SJed Brown   PetscInt       off;
2756552f7358SJed Brown 
2757552f7358SJed Brown   PetscFunctionBegin;
2758552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2759552f7358SJed Brown   PetscValidPointer(cone, 3);
27605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
2761552f7358SJed Brown   *cone = &mesh->cones[off];
2762552f7358SJed Brown   PetscFunctionReturn(0);
2763552f7358SJed Brown }
2764552f7358SJed Brown 
27650ce7577fSVaclav Hapla /*@C
27660ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
27670ce7577fSVaclav Hapla 
27680ce7577fSVaclav Hapla   Not collective
27690ce7577fSVaclav Hapla 
27700ce7577fSVaclav Hapla   Input Parameters:
27710ce7577fSVaclav Hapla + dm - The DMPlex
27720ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
27730ce7577fSVaclav Hapla 
2774d8d19677SJose E. Roman   Output Parameters:
27750ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
27760ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
27770ce7577fSVaclav Hapla 
27780ce7577fSVaclav Hapla   Level: intermediate
27790ce7577fSVaclav Hapla 
2780d4636a37SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart()
27810ce7577fSVaclav Hapla @*/
27820ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
27830ce7577fSVaclav Hapla {
27840ce7577fSVaclav Hapla   PetscSection        cs, newcs;
27850ce7577fSVaclav Hapla   PetscInt            *cones;
27860ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
27870ce7577fSVaclav Hapla   PetscInt            n;
27880ce7577fSVaclav Hapla 
27890ce7577fSVaclav Hapla   PetscFunctionBegin;
27905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCones(dm, &cones));
27915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSection(dm, &cs));
27925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL));
27930ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
27940ce7577fSVaclav Hapla   if (pCones) {
27955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(newcs, &n));
27965f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
27970ce7577fSVaclav Hapla   }
27980ce7577fSVaclav Hapla   PetscFunctionReturn(0);
27990ce7577fSVaclav Hapla }
28000ce7577fSVaclav Hapla 
2801af9eab45SVaclav Hapla /*@
2802af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2803d4636a37SVaclav Hapla 
2804d4636a37SVaclav Hapla   Not collective
2805d4636a37SVaclav Hapla 
2806d4636a37SVaclav Hapla   Input Parameters:
2807d4636a37SVaclav Hapla + dm - The DMPlex
2808af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2809d4636a37SVaclav Hapla 
2810d4636a37SVaclav Hapla   Output Parameter:
2811af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2812d4636a37SVaclav Hapla 
2813d4636a37SVaclav Hapla   Level: advanced
2814d4636a37SVaclav Hapla 
2815af9eab45SVaclav Hapla   Notes:
2816af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2817af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2818af9eab45SVaclav Hapla 
2819af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth()
2820d4636a37SVaclav Hapla @*/
2821af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2822d4636a37SVaclav Hapla {
2823af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2824af9eab45SVaclav Hapla   PetscInt            depth;
2825d4636a37SVaclav Hapla 
2826d4636a37SVaclav Hapla   PetscFunctionBegin;
2827af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2828af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2829af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
28305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2831af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
28325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)expandedPointsAll[0]));
28335f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2834af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2835af9eab45SVaclav Hapla }
2836af9eab45SVaclav Hapla 
2837af9eab45SVaclav Hapla /*@
2838af9eab45SVaclav 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).
2839af9eab45SVaclav Hapla 
2840af9eab45SVaclav Hapla   Not collective
2841af9eab45SVaclav Hapla 
2842af9eab45SVaclav Hapla   Input Parameters:
2843af9eab45SVaclav Hapla + dm - The DMPlex
2844af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2845af9eab45SVaclav Hapla 
2846d8d19677SJose E. Roman   Output Parameters:
2847af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2848af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2849af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2850af9eab45SVaclav Hapla 
2851af9eab45SVaclav Hapla   Level: advanced
2852af9eab45SVaclav Hapla 
2853af9eab45SVaclav Hapla   Notes:
2854af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2855af9eab45SVaclav Hapla 
2856af9eab45SVaclav 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.
2857af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2858af9eab45SVaclav Hapla 
2859af9eab45SVaclav 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:
2860af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2861af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2862af9eab45SVaclav Hapla 
2863af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2864af9eab45SVaclav Hapla @*/
2865af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2866af9eab45SVaclav Hapla {
2867af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2868af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2869af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2870af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2871af9eab45SVaclav Hapla   PetscSection        *sections_;
2872af9eab45SVaclav Hapla 
2873af9eab45SVaclav Hapla   PetscFunctionBegin;
2874af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2875af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2876af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2877af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2878af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
28795f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(points, &n));
28805f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(points, &arr0));
28815f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth_));
28825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(depth_, &expandedPoints_));
28835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(depth_, &sections_));
2884af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2885af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
28865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
28875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(sections_[d], 0, n));
2888af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
28895f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetDepthStratum(dm, d+1, &start, &end));
2890af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
28915f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(dm, arr[i], &cn));
28925f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionSetDof(sections_[d], i, cn));
2893af9eab45SVaclav Hapla       } else {
28945f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionSetDof(sections_[d], i, 1));
2895af9eab45SVaclav Hapla       }
2896af9eab45SVaclav Hapla     }
28975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(sections_[d]));
28985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(sections_[d], &newn));
28995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(newn, &newarr));
2900af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(sections_[d], i, &cn));
29025f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(sections_[d], i, &co));
2903af9eab45SVaclav Hapla       if (cn > 1) {
29045f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, arr[i], &cone));
29055f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt)));
2906af9eab45SVaclav Hapla       } else {
2907af9eab45SVaclav Hapla         newarr[co] = arr[i];
2908af9eab45SVaclav Hapla       }
2909af9eab45SVaclav Hapla     }
29105f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2911af9eab45SVaclav Hapla     arr = newarr;
2912af9eab45SVaclav Hapla     n = newn;
2913af9eab45SVaclav Hapla   }
29145f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(points, &arr0));
2915af9eab45SVaclav Hapla   *depth = depth_;
2916af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2917af9eab45SVaclav Hapla   else {
29185f80ce2aSJacob Faibussowitsch     for (d=0; d<depth_; d++) CHKERRQ(ISDestroy(&expandedPoints_[d]));
29195f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(expandedPoints_));
2920af9eab45SVaclav Hapla   }
2921af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2922af9eab45SVaclav Hapla   else {
29235f80ce2aSJacob Faibussowitsch     for (d=0; d<depth_; d++) CHKERRQ(PetscSectionDestroy(&sections_[d]));
29245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(sections_));
2925af9eab45SVaclav Hapla   }
2926af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2927af9eab45SVaclav Hapla }
2928af9eab45SVaclav Hapla 
2929af9eab45SVaclav Hapla /*@
2930af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2931af9eab45SVaclav Hapla 
2932af9eab45SVaclav Hapla   Not collective
2933af9eab45SVaclav Hapla 
2934af9eab45SVaclav Hapla   Input Parameters:
2935af9eab45SVaclav Hapla + dm - The DMPlex
2936af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2937af9eab45SVaclav Hapla 
2938d8d19677SJose E. Roman   Output Parameters:
2939af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2940af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2941af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2942af9eab45SVaclav Hapla 
2943af9eab45SVaclav Hapla   Level: advanced
2944af9eab45SVaclav Hapla 
2945af9eab45SVaclav Hapla   Notes:
2946af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2947af9eab45SVaclav Hapla 
2948af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2949af9eab45SVaclav Hapla @*/
2950af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2951af9eab45SVaclav Hapla {
2952af9eab45SVaclav Hapla   PetscInt            d, depth_;
2953af9eab45SVaclav Hapla 
2954af9eab45SVaclav Hapla   PetscFunctionBegin;
29555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth_));
29562c71b3e2SJacob Faibussowitsch   PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2957af9eab45SVaclav Hapla   if (depth) *depth = 0;
2958af9eab45SVaclav Hapla   if (expandedPoints) {
29595f80ce2aSJacob Faibussowitsch     for (d=0; d<depth_; d++) CHKERRQ(ISDestroy(&((*expandedPoints)[d])));
29605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(*expandedPoints));
2961af9eab45SVaclav Hapla   }
2962af9eab45SVaclav Hapla   if (sections)  {
29635f80ce2aSJacob Faibussowitsch     for (d=0; d<depth_; d++) CHKERRQ(PetscSectionDestroy(&((*sections)[d])));
29645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(*sections));
2965af9eab45SVaclav Hapla   }
2966d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2967d4636a37SVaclav Hapla }
2968d4636a37SVaclav Hapla 
2969552f7358SJed Brown /*@
297092371b87SBarry 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
2971552f7358SJed Brown 
2972552f7358SJed Brown   Not collective
2973552f7358SJed Brown 
2974552f7358SJed Brown   Input Parameters:
2975552f7358SJed Brown + mesh - The DMPlex
2976eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2977552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
2978552f7358SJed Brown 
2979552f7358SJed Brown   Output Parameter:
2980552f7358SJed Brown 
2981552f7358SJed Brown   Note:
2982552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
2983552f7358SJed Brown 
2984552f7358SJed Brown   Level: beginner
2985552f7358SJed Brown 
298692371b87SBarry Smith .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize()
2987552f7358SJed Brown @*/
2988552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
2989552f7358SJed Brown {
2990552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2991552f7358SJed Brown   PetscInt       pStart, pEnd;
2992552f7358SJed Brown   PetscInt       dof, off, c;
2993552f7358SJed Brown 
2994552f7358SJed Brown   PetscFunctionBegin;
2995552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
29975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
2998*dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
29995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
30002c71b3e2SJacob 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);
3001552f7358SJed Brown   for (c = 0; c < dof; ++c) {
30022c71b3e2SJacob 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);
3003552f7358SJed Brown     mesh->cones[off+c] = cone[c];
3004552f7358SJed Brown   }
3005552f7358SJed Brown   PetscFunctionReturn(0);
3006552f7358SJed Brown }
3007552f7358SJed Brown 
3008552f7358SJed Brown /*@C
3009eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3010552f7358SJed Brown 
3011552f7358SJed Brown   Not collective
3012552f7358SJed Brown 
3013552f7358SJed Brown   Input Parameters:
3014552f7358SJed Brown + mesh - The DMPlex
3015eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3016552f7358SJed Brown 
3017552f7358SJed Brown   Output Parameter:
3018552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3019b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3020552f7358SJed Brown 
3021552f7358SJed Brown   Level: beginner
3022552f7358SJed Brown 
3023b5a892a1SMatthew G. Knepley   Notes:
3024b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3025b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3026b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
3027b5a892a1SMatthew G. Knepley   with the identity.
3028b5a892a1SMatthew G. Knepley 
30293813dfbdSMatthew G Knepley   Fortran Notes:
30303813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30313813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30323b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
3033922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
30343813dfbdSMatthew G Knepley 
3035b5a892a1SMatthew G. Knepley .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart()
3036552f7358SJed Brown @*/
3037552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3038552f7358SJed Brown {
3039552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3040552f7358SJed Brown   PetscInt       off;
3041552f7358SJed Brown 
3042552f7358SJed Brown   PetscFunctionBegin;
3043552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
304476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3045552f7358SJed Brown     PetscInt dof;
30465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
3047552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3048552f7358SJed Brown   }
30495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
30500d644c17SKarl Rupp 
3051552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3052552f7358SJed Brown   PetscFunctionReturn(0);
3053552f7358SJed Brown }
3054552f7358SJed Brown 
3055552f7358SJed Brown /*@
3056eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3057552f7358SJed Brown 
3058552f7358SJed Brown   Not collective
3059552f7358SJed Brown 
3060552f7358SJed Brown   Input Parameters:
3061552f7358SJed Brown + mesh - The DMPlex
3062eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3063b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3064552f7358SJed Brown   Output Parameter:
3065552f7358SJed Brown 
3066b5a892a1SMatthew G. Knepley   Notes:
3067552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3068552f7358SJed Brown 
3069b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3070b5a892a1SMatthew G. Knepley 
3071552f7358SJed Brown   Level: beginner
3072552f7358SJed Brown 
3073552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
3074552f7358SJed Brown @*/
3075552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3076552f7358SJed Brown {
3077552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3078552f7358SJed Brown   PetscInt       pStart, pEnd;
3079552f7358SJed Brown   PetscInt       dof, off, c;
3080552f7358SJed Brown 
3081552f7358SJed Brown   PetscFunctionBegin;
3082552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
3085*dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
30865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
30872c71b3e2SJacob 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);
3088552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3089552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3090552f7358SJed Brown 
30915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof));
30922c71b3e2SJacob 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);
3093552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
3094552f7358SJed Brown   }
3095552f7358SJed Brown   PetscFunctionReturn(0);
3096552f7358SJed Brown }
3097552f7358SJed Brown 
30987cd05799SMatthew G. Knepley /*@
3099eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31007cd05799SMatthew G. Knepley 
31017cd05799SMatthew G. Knepley   Not collective
31027cd05799SMatthew G. Knepley 
31037cd05799SMatthew G. Knepley   Input Parameters:
31047cd05799SMatthew G. Knepley + mesh - The DMPlex
3105eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31067cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31077cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31087cd05799SMatthew G. Knepley 
31097cd05799SMatthew G. Knepley   Level: beginner
31107cd05799SMatthew G. Knepley 
31117cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
31127cd05799SMatthew G. Knepley @*/
3113552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3114552f7358SJed Brown {
3115552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3116552f7358SJed Brown   PetscInt       pStart, pEnd;
3117552f7358SJed Brown   PetscInt       dof, off;
3118552f7358SJed Brown 
3119552f7358SJed Brown   PetscFunctionBegin;
3120552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31222c71b3e2SJacob 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);
31232c71b3e2SJacob 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);
31245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
31255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
31262c71b3e2SJacob 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);
3127552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
3128552f7358SJed Brown   PetscFunctionReturn(0);
3129552f7358SJed Brown }
3130552f7358SJed Brown 
31317cd05799SMatthew G. Knepley /*@
3132eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
31337cd05799SMatthew G. Knepley 
31347cd05799SMatthew G. Knepley   Not collective
31357cd05799SMatthew G. Knepley 
31367cd05799SMatthew G. Knepley   Input Parameters:
31377cd05799SMatthew G. Knepley + mesh - The DMPlex
3138eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31397cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31407cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
31417cd05799SMatthew G. Knepley 
31427cd05799SMatthew G. Knepley   Level: beginner
31437cd05799SMatthew G. Knepley 
3144b5a892a1SMatthew G. Knepley   Notes:
3145b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3146b5a892a1SMatthew G. Knepley 
31477cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
31487cd05799SMatthew G. Knepley @*/
314977c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
315077c88f5bSMatthew G Knepley {
315177c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
315277c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
315377c88f5bSMatthew G Knepley   PetscInt       dof, off;
315477c88f5bSMatthew G Knepley 
315577c88f5bSMatthew G Knepley   PetscFunctionBegin;
315677c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31582c71b3e2SJacob 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);
31595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
31605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
31612c71b3e2SJacob 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);
316277c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
316377c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
316477c88f5bSMatthew G Knepley }
316577c88f5bSMatthew G Knepley 
3166552f7358SJed Brown /*@
3167eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3168552f7358SJed Brown 
3169552f7358SJed Brown   Not collective
3170552f7358SJed Brown 
3171552f7358SJed Brown   Input Parameters:
3172552f7358SJed Brown + mesh - The DMPlex
3173eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3174552f7358SJed Brown 
3175552f7358SJed Brown   Output Parameter:
3176552f7358SJed Brown . size - The support size for point p
3177552f7358SJed Brown 
3178552f7358SJed Brown   Level: beginner
3179552f7358SJed Brown 
3180552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize()
3181552f7358SJed Brown @*/
3182552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3183552f7358SJed Brown {
3184552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3185552f7358SJed Brown 
3186552f7358SJed Brown   PetscFunctionBegin;
3187552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3188*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
31895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, size));
3190552f7358SJed Brown   PetscFunctionReturn(0);
3191552f7358SJed Brown }
3192552f7358SJed Brown 
3193552f7358SJed Brown /*@
3194eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3195552f7358SJed Brown 
3196552f7358SJed Brown   Not collective
3197552f7358SJed Brown 
3198552f7358SJed Brown   Input Parameters:
3199552f7358SJed Brown + mesh - The DMPlex
3200eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3201552f7358SJed Brown - size - The support size for point p
3202552f7358SJed Brown 
3203552f7358SJed Brown   Output Parameter:
3204552f7358SJed Brown 
3205552f7358SJed Brown   Note:
3206552f7358SJed Brown   This should be called after DMPlexSetChart().
3207552f7358SJed Brown 
3208552f7358SJed Brown   Level: beginner
3209552f7358SJed Brown 
3210552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart()
3211552f7358SJed Brown @*/
3212552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3213552f7358SJed Brown {
3214552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3215552f7358SJed Brown 
3216552f7358SJed Brown   PetscFunctionBegin;
3217552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetDof(mesh->supportSection, p, size));
32190d644c17SKarl Rupp 
3220552f7358SJed Brown   mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size);
3221552f7358SJed Brown   PetscFunctionReturn(0);
3222552f7358SJed Brown }
3223552f7358SJed Brown 
3224552f7358SJed Brown /*@C
3225eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3226552f7358SJed Brown 
3227552f7358SJed Brown   Not collective
3228552f7358SJed Brown 
3229552f7358SJed Brown   Input Parameters:
3230552f7358SJed Brown + mesh - The DMPlex
3231eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3232552f7358SJed Brown 
3233552f7358SJed Brown   Output Parameter:
3234552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3235552f7358SJed Brown 
3236552f7358SJed Brown   Level: beginner
3237552f7358SJed Brown 
32383813dfbdSMatthew G Knepley   Fortran Notes:
32393813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32403813dfbdSMatthew G Knepley   include petsc.h90 in your code.
32413b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3242922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
32433813dfbdSMatthew G Knepley 
3244e45f02b0SMatthew G. Knepley .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart()
3245552f7358SJed Brown @*/
3246552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3247552f7358SJed Brown {
3248552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3249552f7358SJed Brown   PetscInt       off;
3250552f7358SJed Brown 
3251552f7358SJed Brown   PetscFunctionBegin;
3252552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3253552f7358SJed Brown   PetscValidPointer(support, 3);
32545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off));
3255552f7358SJed Brown   *support = &mesh->supports[off];
3256552f7358SJed Brown   PetscFunctionReturn(0);
3257552f7358SJed Brown }
3258552f7358SJed Brown 
3259552f7358SJed Brown /*@
326092371b87SBarry 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
3261552f7358SJed Brown 
3262552f7358SJed Brown   Not collective
3263552f7358SJed Brown 
3264552f7358SJed Brown   Input Parameters:
3265552f7358SJed Brown + mesh - The DMPlex
3266eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
326792371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3268552f7358SJed Brown 
3269552f7358SJed Brown   Output Parameter:
3270552f7358SJed Brown 
3271552f7358SJed Brown   Note:
3272552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3273552f7358SJed Brown 
3274552f7358SJed Brown   Level: beginner
3275552f7358SJed Brown 
327692371b87SBarry Smith .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp()
3277552f7358SJed Brown @*/
3278552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3279552f7358SJed Brown {
3280552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3281552f7358SJed Brown   PetscInt       pStart, pEnd;
3282552f7358SJed Brown   PetscInt       dof, off, c;
3283552f7358SJed Brown 
3284552f7358SJed Brown   PetscFunctionBegin;
3285552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
32875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof));
3288*dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
32895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off));
32902c71b3e2SJacob 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);
3291552f7358SJed Brown   for (c = 0; c < dof; ++c) {
32922c71b3e2SJacob 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);
3293552f7358SJed Brown     mesh->supports[off+c] = support[c];
3294552f7358SJed Brown   }
3295552f7358SJed Brown   PetscFunctionReturn(0);
3296552f7358SJed Brown }
3297552f7358SJed Brown 
32987cd05799SMatthew G. Knepley /*@
3299eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
33007cd05799SMatthew G. Knepley 
33017cd05799SMatthew G. Knepley   Not collective
33027cd05799SMatthew G. Knepley 
33037cd05799SMatthew G. Knepley   Input Parameters:
33047cd05799SMatthew G. Knepley + mesh - The DMPlex
3305eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
33067cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
33077cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
33087cd05799SMatthew G. Knepley 
33097cd05799SMatthew G. Knepley   Level: beginner
33107cd05799SMatthew G. Knepley 
33117cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
33127cd05799SMatthew G. Knepley @*/
3313552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3314552f7358SJed Brown {
3315552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3316552f7358SJed Brown   PetscInt       pStart, pEnd;
3317552f7358SJed Brown   PetscInt       dof, off;
3318552f7358SJed Brown 
3319552f7358SJed Brown   PetscFunctionBegin;
3320552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof));
33235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->supportSection, p, &off));
33242c71b3e2SJacob 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);
33252c71b3e2SJacob 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);
33262c71b3e2SJacob 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);
3327552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3328552f7358SJed Brown   PetscFunctionReturn(0);
3329552f7358SJed Brown }
3330552f7358SJed Brown 
3331b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3332b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3333b5a892a1SMatthew G. Knepley {
3334b5a892a1SMatthew G. Knepley   switch (ct) {
3335b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3336b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3337b5a892a1SMatthew G. Knepley       break;
3338b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3339b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3340b5a892a1SMatthew G. Knepley       if (o == -2) return -3;
3341b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3342b5a892a1SMatthew G. Knepley       break;
3343b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3344b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3345b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3346b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3347b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3348b5a892a1SMatthew G. Knepley       break;
3349b5a892a1SMatthew G. Knepley     default: return o;
3350b5a892a1SMatthew G. Knepley   }
3351b5a892a1SMatthew G. Knepley   return o;
3352b5a892a1SMatthew G. Knepley }
3353b5a892a1SMatthew G. Knepley 
3354b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3355b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3356b5a892a1SMatthew G. Knepley {
3357b5a892a1SMatthew G. Knepley   switch (ct) {
3358b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3359b5a892a1SMatthew G. Knepley       if ((o == -2) || (o == 1)) return -1;
3360b5a892a1SMatthew G. Knepley       if (o == -1) return 0;
3361b5a892a1SMatthew G. Knepley       break;
3362b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3363b5a892a1SMatthew G. Knepley       if (o == -3) return -2;
3364b5a892a1SMatthew G. Knepley       if (o == -2) return -1;
3365b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3366b5a892a1SMatthew G. Knepley       break;
3367b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3368b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3369b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3370b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3371b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3372b5a892a1SMatthew G. Knepley       break;
3373b5a892a1SMatthew G. Knepley     default: return o;
3374b5a892a1SMatthew G. Knepley   }
3375b5a892a1SMatthew G. Knepley   return o;
3376b5a892a1SMatthew G. Knepley }
3377b5a892a1SMatthew G. Knepley 
3378b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3379b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3380b5a892a1SMatthew G. Knepley {
3381b5a892a1SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3382b5a892a1SMatthew G. Knepley 
3383b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
33845f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
3385b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3386b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3387b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3388b5a892a1SMatthew G. Knepley 
33895f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
33905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, p, &cone));
33915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeOrientation(dm, p, &ornt));
3392b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3393b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3394b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3395b5a892a1SMatthew G. Knepley 
33965f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, cone[c], &ct));
3397b5a892a1SMatthew G. Knepley       switch (ct) {
3398b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
33995f80ce2aSJacob Faibussowitsch           if ((o == -2) || (o == 1)) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -1));
34005f80ce2aSJacob Faibussowitsch           if (o == -1) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, 0));
3401b5a892a1SMatthew G. Knepley           break;
3402b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
34035f80ce2aSJacob Faibussowitsch           if (o == -3) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -2));
34045f80ce2aSJacob Faibussowitsch           if (o == -2) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -1));
34055f80ce2aSJacob Faibussowitsch           if (o == -1) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -3));
3406b5a892a1SMatthew G. Knepley           break;
3407b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
34085f80ce2aSJacob Faibussowitsch           if (o == -4) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -2));
34095f80ce2aSJacob Faibussowitsch           if (o == -3) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -1));
34105f80ce2aSJacob Faibussowitsch           if (o == -2) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -4));
34115f80ce2aSJacob Faibussowitsch           if (o == -1) CHKERRQ(DMPlexInsertConeOrientation(dm, p, c, -3));
3412b5a892a1SMatthew G. Knepley           break;
3413b5a892a1SMatthew G. Knepley         default: break;
3414b5a892a1SMatthew G. Knepley       }
3415b5a892a1SMatthew G. Knepley     }
3416b5a892a1SMatthew G. Knepley   }
3417b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3418b5a892a1SMatthew G. Knepley }
3419b5a892a1SMatthew G. Knepley 
3420012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3421b5a892a1SMatthew G. Knepley {
3422b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3423b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3424b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3425b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3426b5a892a1SMatthew G. Knepley 
3427b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3428b5a892a1SMatthew G. Knepley   if (ornt) {
34295f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, p, &ct));
3430b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3431b5a892a1SMatthew G. Knepley   }
3432b5a892a1SMatthew G. Knepley   if (*points) {
3433b5a892a1SMatthew G. Knepley     closure = *points;
3434b5a892a1SMatthew G. Knepley   } else {
3435b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
34365f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
34375f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure));
3438b5a892a1SMatthew G. Knepley   }
3439b5a892a1SMatthew G. Knepley   if (useCone) {
34405f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, p, &tmpSize));
34415f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, p, &tmp));
34425f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeOrientation(dm, p, &tmpO));
3443b5a892a1SMatthew G. Knepley   } else {
34445f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupportSize(dm, p, &tmpSize));
34455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupport(dm, p, &tmp));
3446b5a892a1SMatthew G. Knepley   }
3447b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3448b5a892a1SMatthew G. Knepley     closure[off++] = p;
3449b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3450b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3451b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3452b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3453b5a892a1SMatthew G. Knepley     }
3454b5a892a1SMatthew G. Knepley   } else {
34555f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3456b5a892a1SMatthew G. Knepley 
3457b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3458b5a892a1SMatthew G. Knepley     closure[off++] = p;
3459b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3460b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3461b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3462b5a892a1SMatthew G. Knepley 
34635f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, tmp[t], &ft));
3464b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3465b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3466b5a892a1SMatthew G. Knepley     }
3467b5a892a1SMatthew G. Knepley   }
3468b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize+1;
3469b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3470b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3471b5a892a1SMatthew G. Knepley }
3472b5a892a1SMatthew G. Knepley 
3473b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
3474b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3475b5a892a1SMatthew G. Knepley {
3476b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3477b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3478b5a892a1SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
3479b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3480b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3481b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3482b5a892a1SMatthew G. Knepley 
3483b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
34845f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
34855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize));
34865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCone(dm, point, &cone));
34875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeOrientation(dm, point, &ornt));
34885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3489b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    dim+1)-1)/(maxConeSize-1))    : dim+1;
3490b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1;
3491b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3492b5a892a1SMatthew G. Knepley   if (*points) {pts  = *points;}
34935f80ce2aSJacob Faibussowitsch   else         CHKERRQ(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts));
3494b5a892a1SMatthew G. Knepley   c    = 0;
3495b5a892a1SMatthew G. Knepley   pts[c++] = point;
3496b5a892a1SMatthew G. Knepley   pts[c++] = o;
34975f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft));
34985f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure));
3499b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure));
3501b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35025f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3503b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
35045f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft));
3505b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d*2+0]];
3506b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]);
3507b5a892a1SMatthew G. Knepley   }
3508b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3509b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3510b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d*2+0]];
3511b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3512b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3513b5a892a1SMatthew G. Knepley 
35145f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, fpoint, &ft));
3515b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]));
35165f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, fpoint, &fconeSize));
35175f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, fpoint, &fcone));
35185f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3519b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3520b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc*2+0]];
3521b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc*2+1];
3522b5a892a1SMatthew G. Knepley 
3523b5a892a1SMatthew G. Knepley         for (i = 0; i < c; i += 2) if (pts[i] == cp) break;
3524b5a892a1SMatthew G. Knepley         if (i == c) {
35255f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetCellType(dm, cp, &ft));
3526b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3527b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]);
3528b5a892a1SMatthew G. Knepley         }
3529b5a892a1SMatthew G. Knepley       }
3530b5a892a1SMatthew G. Knepley     }
3531b5a892a1SMatthew G. Knepley   }
3532b5a892a1SMatthew G. Knepley   *numPoints = c/2;
3533b5a892a1SMatthew G. Knepley   *points    = pts;
3534b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3535b5a892a1SMatthew G. Knepley }
3536b5a892a1SMatthew G. Knepley 
3537b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3538b5a892a1SMatthew G. Knepley {
3539b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3540b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3541b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3542b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3543b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3544b5a892a1SMatthew G. Knepley 
3545b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
3547b5a892a1SMatthew G. Knepley   if (depth == 1) {
35485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3549b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3550b5a892a1SMatthew G. Knepley   }
35515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dm, p, &ct));
3552b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3553b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
35545f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3555b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3556b5a892a1SMatthew G. Knepley   }
35575f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3558b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    depth+1)-1)/(maxConeSize-1))    : depth+1;
3559b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1;
3560b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
35615f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3562b5a892a1SMatthew G. Knepley   if (*points) {closure = *points;}
35635f80ce2aSJacob Faibussowitsch   else         CHKERRQ(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure));
3564b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3565b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3566b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3567b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3568b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3569b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3570b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3571b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3572b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3573b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType) fifo[fifoStart++];
3574b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3575b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3576b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3577b5a892a1SMatthew G. Knepley 
3578b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3579b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2;
35802c71b3e2SJacob 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);
3581b5a892a1SMatthew G. Knepley     }
3582b5a892a1SMatthew G. Knepley     if (useCone) {
35835f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, q, &tmpSize));
35845f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, q, &tmp));
35855f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeOrientation(dm, q, &tmpO));
3586b5a892a1SMatthew G. Knepley     } else {
35875f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupportSize(dm, q, &tmpSize));
35885f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupport(dm, q, &tmp));
3589b5a892a1SMatthew G. Knepley       tmpO = NULL;
3590b5a892a1SMatthew G. Knepley     }
3591b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3592b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t*2]   : t;
3593b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0;
3594b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
35955f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, cp, &ct));
3596b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3597b5a892a1SMatthew G. Knepley       PetscInt       c;
3598b5a892a1SMatthew G. Knepley 
3599b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3600b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3601b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3602b5a892a1SMatthew G. Knepley       }
3603b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3604b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3605b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3606b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3607b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3608b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3609b5a892a1SMatthew G. Knepley       }
3610b5a892a1SMatthew G. Knepley     }
3611b5a892a1SMatthew G. Knepley   }
36125f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3613b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
3614b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3615b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3616b5a892a1SMatthew G. Knepley }
3617b5a892a1SMatthew G. Knepley 
3618552f7358SJed Brown /*@C
3619eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3620552f7358SJed Brown 
3621552f7358SJed Brown   Not collective
3622552f7358SJed Brown 
3623552f7358SJed Brown   Input Parameters:
3624b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3625b5a892a1SMatthew G. Knepley . p       - The mesh point
36266b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3627552f7358SJed Brown 
36286b867d5aSJose E. Roman   Input/Output Parameter:
36296b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
36306b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
36316b867d5aSJose E. Roman 
36326b867d5aSJose E. Roman   Output Parameter:
36336b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3634552f7358SJed Brown 
3635552f7358SJed Brown   Note:
36360298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3637552f7358SJed Brown 
36383813dfbdSMatthew G Knepley   Fortran Notes:
3639b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36403813dfbdSMatthew G Knepley 
36413813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36423813dfbdSMatthew G Knepley 
3643552f7358SJed Brown   Level: beginner
3644552f7358SJed Brown 
3645552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3646552f7358SJed Brown @*/
3647552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3648552f7358SJed Brown {
3649b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3650552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3651b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3652b5a892a1SMatthew G. Knepley   if (points)    PetscValidPointer(points, 5);
36535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
36549bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36559bf0dad6SMatthew G. Knepley }
36569bf0dad6SMatthew G. Knepley 
3657552f7358SJed Brown /*@C
3658eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3659552f7358SJed Brown 
3660552f7358SJed Brown   Not collective
3661552f7358SJed Brown 
3662552f7358SJed Brown   Input Parameters:
3663b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3664b5a892a1SMatthew G. Knepley . p         - The mesh point
3665b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3666b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3667b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3668552f7358SJed Brown 
3669552f7358SJed Brown   Note:
36700298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3671552f7358SJed Brown 
36723813dfbdSMatthew G Knepley   Fortran Notes:
3673b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36743813dfbdSMatthew G Knepley 
36753813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36763813dfbdSMatthew G Knepley 
3677552f7358SJed Brown   Level: beginner
3678552f7358SJed Brown 
3679552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3680552f7358SJed Brown @*/
3681552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3682552f7358SJed Brown {
3683b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3684552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36854ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
36865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3687552f7358SJed Brown   PetscFunctionReturn(0);
3688552f7358SJed Brown }
3689552f7358SJed Brown 
3690552f7358SJed Brown /*@
3691eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3692552f7358SJed Brown 
3693552f7358SJed Brown   Not collective
3694552f7358SJed Brown 
3695552f7358SJed Brown   Input Parameter:
3696552f7358SJed Brown . mesh - The DMPlex
3697552f7358SJed Brown 
3698552f7358SJed Brown   Output Parameters:
3699552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3700552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3701552f7358SJed Brown 
3702552f7358SJed Brown   Level: beginner
3703552f7358SJed Brown 
3704552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
3705552f7358SJed Brown @*/
3706552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3707552f7358SJed Brown {
3708552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3709552f7358SJed Brown 
3710552f7358SJed Brown   PetscFunctionBegin;
3711552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3712552f7358SJed Brown   if (maxConeSize)    *maxConeSize    = mesh->maxConeSize;
3713552f7358SJed Brown   if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize;
3714552f7358SJed Brown   PetscFunctionReturn(0);
3715552f7358SJed Brown }
3716552f7358SJed Brown 
3717552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3718552f7358SJed Brown {
3719552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3720552f7358SJed Brown   PetscInt       size;
3721552f7358SJed Brown 
3722552f7358SJed Brown   PetscFunctionBegin;
3723552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(mesh->coneSection));
37255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(mesh->coneSection, &size));
37265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(size, &mesh->cones));
37275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(size, &mesh->coneOrientations));
37285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt)));
3729552f7358SJed Brown   if (mesh->maxSupportSize) {
37305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(mesh->supportSection));
37315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(mesh->supportSection, &size));
37325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(size, &mesh->supports));
37335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt)));
3734552f7358SJed Brown   }
3735552f7358SJed Brown   PetscFunctionReturn(0);
3736552f7358SJed Brown }
3737552f7358SJed Brown 
3738276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3739552f7358SJed Brown {
3740552f7358SJed Brown   PetscFunctionBegin;
37415f80ce2aSJacob Faibussowitsch   if (subdm) CHKERRQ(DMClone(dm, subdm));
37425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3743c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3744736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3745f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3746f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3747f94b4a02SBlaise Bourdin 
37483dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject) dm->sfMigration));
37505f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection((*subdm), &section));
37515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv));
37525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq));
37535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
3754f94b4a02SBlaise Bourdin 
37555f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural));
3756c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
37575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionDestroy(&sectionSeq));
37585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sfMigrationInv));
3759f94b4a02SBlaise Bourdin   }
3760552f7358SJed Brown   PetscFunctionReturn(0);
3761552f7358SJed Brown }
3762552f7358SJed Brown 
37632adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
37642adcc780SMatthew G. Knepley {
37653dcd263cSBlaise Bourdin   PetscInt       i = 0;
37662adcc780SMatthew G. Knepley 
37672adcc780SMatthew G. Knepley   PetscFunctionBegin;
37685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMClone(dms[0], superdm));
37695f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateSectionSuperDM(dms, len, is, superdm));
3770c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
37713dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
37723dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
37733dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
37743dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
37753dcd263cSBlaise Bourdin 
37763dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
37775f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject) dms[i]->sfMigration));
3778c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
37795f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLocalSection((*superdm), &section));
37805f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv));
37815f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq));
37825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
37833dcd263cSBlaise Bourdin 
37845f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural));
3785c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
37865f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionDestroy(&sectionSeq));
37875f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFDestroy(&sfMigrationInv));
37883dcd263cSBlaise Bourdin       break;
37893dcd263cSBlaise Bourdin     }
37903dcd263cSBlaise Bourdin   }
37912adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
37922adcc780SMatthew G. Knepley }
37932adcc780SMatthew G. Knepley 
3794552f7358SJed Brown /*@
3795eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3796552f7358SJed Brown 
3797552f7358SJed Brown   Not collective
3798552f7358SJed Brown 
3799552f7358SJed Brown   Input Parameter:
3800552f7358SJed Brown . mesh - The DMPlex
3801552f7358SJed Brown 
3802552f7358SJed Brown   Output Parameter:
3803552f7358SJed Brown 
3804552f7358SJed Brown   Note:
3805552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3806552f7358SJed Brown 
3807552f7358SJed Brown   Level: beginner
3808552f7358SJed Brown 
3809552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone()
3810552f7358SJed Brown @*/
3811552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3812552f7358SJed Brown {
3813552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3814552f7358SJed Brown   PetscInt      *offsets;
3815552f7358SJed Brown   PetscInt       supportSize;
3816552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3817552f7358SJed Brown 
3818552f7358SJed Brown   PetscFunctionBegin;
3819552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
382028b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
38215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0));
3822552f7358SJed Brown   /* Calculate support sizes */
38235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
3824552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3825552f7358SJed Brown     PetscInt dof, off, c;
3826552f7358SJed Brown 
38275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
38285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
3829552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
38305f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3831552f7358SJed Brown     }
3832552f7358SJed Brown   }
3833552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3834552f7358SJed Brown     PetscInt dof;
3835552f7358SJed Brown 
38365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->supportSection, p, &dof));
38370d644c17SKarl Rupp 
3838552f7358SJed Brown     mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof);
3839552f7358SJed Brown   }
38405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(mesh->supportSection));
3841552f7358SJed Brown   /* Calculate supports */
38425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
38435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(supportSize, &mesh->supports));
38445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(pEnd - pStart, &offsets));
3845552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3846552f7358SJed Brown     PetscInt dof, off, c;
3847552f7358SJed Brown 
38485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->coneSection, p, &dof));
38495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(mesh->coneSection, p, &off));
3850552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3851552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3852552f7358SJed Brown       PetscInt       offS;
3853552f7358SJed Brown 
38545f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(mesh->supportSection, q, &offS));
38550d644c17SKarl Rupp 
3856552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3857552f7358SJed Brown       ++offsets[q];
3858552f7358SJed Brown     }
3859552f7358SJed Brown   }
38605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(offsets));
38615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0));
3862552f7358SJed Brown   PetscFunctionReturn(0);
3863552f7358SJed Brown }
3864552f7358SJed Brown 
3865277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3866277ea44aSLisandro Dalcin {
3867277ea44aSLisandro Dalcin   IS             stratumIS;
3868277ea44aSLisandro Dalcin 
3869277ea44aSLisandro Dalcin   PetscFunctionBegin;
3870277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
387176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3872277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3873277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
38745f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetNumValues(label, &numLevels));
3875277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
38765f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3877277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3878277ea44aSLisandro Dalcin     }
387928b400f6SJacob 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);
3880277ea44aSLisandro Dalcin   }
38815f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS));
38825f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelSetStratumIS(label, depth, stratumIS));
38835f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&stratumIS));
3884277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3885277ea44aSLisandro Dalcin }
3886277ea44aSLisandro Dalcin 
3887552f7358SJed Brown /*@
3888a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
38896dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3890552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3891552f7358SJed Brown   the DAG.
3892552f7358SJed Brown 
3893bf4602e4SToby Isaac   Collective on dm
3894552f7358SJed Brown 
3895552f7358SJed Brown   Input Parameter:
3896552f7358SJed Brown . mesh - The DMPlex
3897552f7358SJed Brown 
3898552f7358SJed Brown   Output Parameter:
3899552f7358SJed Brown 
3900552f7358SJed Brown   Notes:
3901b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3902b1bb481bSMatthew 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
3903b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3904c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3905150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3906552f7358SJed Brown 
3907b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3908b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3909b1bb481bSMatthew 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
3910b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3911b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3912b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3913b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3914b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3915b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3916b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3917b1bb481bSMatthew Knepley 
3918150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3919552f7358SJed Brown 
3920552f7358SJed Brown   Level: beginner
3921552f7358SJed Brown 
3922ba2698f1SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes()
3923552f7358SJed Brown @*/
3924552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3925552f7358SJed Brown {
3926df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3927aa50250dSMatthew G. Knepley   DMLabel        label;
3928552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3929552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3930552f7358SJed Brown 
3931552f7358SJed Brown   PetscFunctionBegin;
3932552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0));
3934277ea44aSLisandro Dalcin 
3935277ea44aSLisandro Dalcin   /* Create depth label */
39365f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
39375f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, "depth"));
39385f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &label));
3939277ea44aSLisandro Dalcin 
3940277ea44aSLisandro Dalcin   {
3941552f7358SJed Brown     /* Initialize roots and count leaves */
3942277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3943277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3944552f7358SJed Brown     PetscInt coneSize, supportSize;
3945552f7358SJed Brown 
3946277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39475f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
39485f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize));
3949552f7358SJed Brown       if (!coneSize && supportSize) {
3950277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3951277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3952552f7358SJed Brown         ++numRoots;
3953552f7358SJed Brown       } else if (!supportSize && coneSize) {
3954552f7358SJed Brown         ++numLeaves;
3955552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3956552f7358SJed Brown         /* Isolated points */
3957277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3958277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3959552f7358SJed Brown       }
3960552f7358SJed Brown     }
39615f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1));
3962277ea44aSLisandro Dalcin   }
3963277ea44aSLisandro Dalcin 
3964552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3965277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3966277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3967552f7358SJed Brown     PetscInt coneSize, supportSize;
3968552f7358SJed Brown 
3969277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39705f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
39715f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize));
3972552f7358SJed Brown       if (!supportSize && coneSize) {
3973277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3974277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3975552f7358SJed Brown       }
3976552f7358SJed Brown     }
39775f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1));
3978552f7358SJed Brown   } else {
3979277ea44aSLisandro Dalcin     PetscInt level = 0;
3980277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3981552f7358SJed Brown 
39825f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3983277ea44aSLisandro Dalcin     while (qEnd > qStart) {
3984277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
3985277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
398674ef644bSMatthew G. Knepley 
3987277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
398874ef644bSMatthew G. Knepley         const PetscInt *support;
398974ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
399074ef644bSMatthew G. Knepley 
39915f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetSupportSize(dm, q, &supportSize));
39925f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetSupport(dm, q, &support));
399374ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
3994277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
3995277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
3996552f7358SJed Brown         }
3997552f7358SJed Brown       }
39985f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetNumValues(label, &level));
39995f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1));
40005f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
400174ef644bSMatthew G. Knepley     }
400274ef644bSMatthew G. Knepley   }
4003bf4602e4SToby Isaac   { /* just in case there is an empty process */
4004bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4005bf4602e4SToby Isaac 
40065f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetNumValues(label, &numValues));
40075f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm)));
4008bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
40095f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelAddStratum(label, v));
4010bf4602e4SToby Isaac     }
4011bf4602e4SToby Isaac   }
40125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateGet((PetscObject) label, &mesh->depthState));
40135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0));
4014552f7358SJed Brown   PetscFunctionReturn(0);
4015552f7358SJed Brown }
4016552f7358SJed Brown 
4017412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4018ba2698f1SMatthew G. Knepley {
4019412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4020412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4021ba2698f1SMatthew G. Knepley 
4022412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
40235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
40245f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
40255f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
4026ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4027ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4028ba2698f1SMatthew G. Knepley     switch (pdepth) {
4029ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
4030ba2698f1SMatthew G. Knepley       case 1:
4031ba2698f1SMatthew G. Knepley         switch (coneSize) {
4032ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
4033ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4034ba2698f1SMatthew G. Knepley           case 4:
4035ba2698f1SMatthew G. Knepley           switch (dim) {
4036ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
4037ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
4038ba2698f1SMatthew G. Knepley             default: break;
4039ba2698f1SMatthew G. Knepley           }
4040ba2698f1SMatthew G. Knepley           break;
4041da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
4042ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4043ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
4044ba2698f1SMatthew G. Knepley         default: break;
4045ba2698f1SMatthew G. Knepley       }
4046ba2698f1SMatthew G. Knepley     }
4047ba2698f1SMatthew G. Knepley   } else {
4048ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4049ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4050ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4051ba2698f1SMatthew G. Knepley       switch (dim) {
4052ba2698f1SMatthew G. Knepley         case 1:
4053ba2698f1SMatthew G. Knepley           switch (coneSize) {
4054ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
4055ba2698f1SMatthew G. Knepley             default: break;
4056ba2698f1SMatthew G. Knepley           }
4057ba2698f1SMatthew G. Knepley           break;
4058ba2698f1SMatthew G. Knepley         case 2:
4059ba2698f1SMatthew G. Knepley           switch (coneSize) {
4060ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4061ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4062ba2698f1SMatthew G. Knepley             default: break;
4063ba2698f1SMatthew G. Knepley           }
4064ba2698f1SMatthew G. Knepley           break;
4065ba2698f1SMatthew G. Knepley         case 3:
4066ba2698f1SMatthew G. Knepley           switch (coneSize) {
4067ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
4068da9060c4SMatthew G. Knepley             case 5:
4069da9060c4SMatthew G. Knepley             {
4070da9060c4SMatthew G. Knepley               const PetscInt *cone;
4071da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
4072da9060c4SMatthew G. Knepley 
40735f80ce2aSJacob Faibussowitsch               CHKERRQ(DMPlexGetCone(dm, p, &cone));
40745f80ce2aSJacob Faibussowitsch               CHKERRQ(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4075da9060c4SMatthew G. Knepley               switch (faceConeSize) {
4076da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4077da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
4078da9060c4SMatthew G. Knepley               }
4079da9060c4SMatthew G. Knepley             }
4080da9060c4SMatthew G. Knepley             break;
4081ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
4082ba2698f1SMatthew G. Knepley             default: break;
4083ba2698f1SMatthew G. Knepley           }
4084ba2698f1SMatthew G. Knepley           break;
4085ba2698f1SMatthew G. Knepley         default: break;
4086ba2698f1SMatthew G. Knepley       }
4087ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4088ba2698f1SMatthew G. Knepley       switch (coneSize) {
4089ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
4090ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4091ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4092ba2698f1SMatthew G. Knepley         default: break;
4093ba2698f1SMatthew G. Knepley       }
4094ba2698f1SMatthew G. Knepley     }
4095ba2698f1SMatthew G. Knepley   }
4096412e9a14SMatthew G. Knepley   *pt = ct;
4097412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4098ba2698f1SMatthew G. Knepley }
4099412e9a14SMatthew G. Knepley 
4100412e9a14SMatthew G. Knepley /*@
4101412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4102412e9a14SMatthew G. Knepley 
4103412e9a14SMatthew G. Knepley   Collective on dm
4104412e9a14SMatthew G. Knepley 
4105412e9a14SMatthew G. Knepley   Input Parameter:
4106412e9a14SMatthew G. Knepley . mesh - The DMPlex
4107412e9a14SMatthew G. Knepley 
4108412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4109412e9a14SMatthew G. Knepley 
4110412e9a14SMatthew G. Knepley   Level: developer
4111412e9a14SMatthew G. Knepley 
4112412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4113412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4114412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4115412e9a14SMatthew G. Knepley 
4116412e9a14SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel()
4117412e9a14SMatthew G. Knepley @*/
4118412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
4119412e9a14SMatthew G. Knepley {
4120412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
4121412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
4122412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
4123412e9a14SMatthew G. Knepley 
4124412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4125412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4126412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
41275f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(dm, "celltype"));
41285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellTypeLabel(dm, &ctLabel));
41295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
4130412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4131327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4132412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4133412e9a14SMatthew G. Knepley 
41345f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetPointDepth(dm, p, &pdepth));
41355f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
41362c71b3e2SJacob Faibussowitsch     PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p);
41375f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelSetValue(ctLabel, p, ct));
4138412e9a14SMatthew G. Knepley   }
41395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState));
41405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view"));
4141ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4142ba2698f1SMatthew G. Knepley }
4143ba2698f1SMatthew G. Knepley 
4144552f7358SJed Brown /*@C
4145552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4146552f7358SJed Brown 
4147552f7358SJed Brown   Not Collective
4148552f7358SJed Brown 
4149552f7358SJed Brown   Input Parameters:
4150552f7358SJed Brown + dm - The DMPlex object
4151552f7358SJed Brown . numPoints - The number of input points for the join
4152552f7358SJed Brown - points - The input points
4153552f7358SJed Brown 
4154552f7358SJed Brown   Output Parameters:
4155552f7358SJed Brown + numCoveredPoints - The number of points in the join
4156552f7358SJed Brown - coveredPoints - The points in the join
4157552f7358SJed Brown 
4158552f7358SJed Brown   Level: intermediate
4159552f7358SJed Brown 
4160552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4161552f7358SJed Brown 
41623813dfbdSMatthew G Knepley   Fortran Notes:
41633813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41643813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41653813dfbdSMatthew G Knepley 
41663813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41673813dfbdSMatthew G Knepley 
4168552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet()
4169552f7358SJed Brown @*/
4170552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4171552f7358SJed Brown {
4172552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4173552f7358SJed Brown   PetscInt      *join[2];
4174552f7358SJed Brown   PetscInt       joinSize, i = 0;
4175552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4176552f7358SJed Brown 
4177552f7358SJed Brown   PetscFunctionBegin;
4178552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
417948bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
418048bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
418148bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
41825f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]));
41835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]));
4184552f7358SJed Brown   /* Copy in support of first point */
41855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
41865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4187552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
4188552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
4189552f7358SJed Brown   }
4190552f7358SJed Brown   /* Check each successive support */
4191552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4192552f7358SJed Brown     PetscInt newJoinSize = 0;
4193552f7358SJed Brown 
41945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
41955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4196552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4197552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
4198552f7358SJed Brown 
4199552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4200552f7358SJed Brown         if (point == join[i][m]) {
4201552f7358SJed Brown           join[1-i][newJoinSize++] = point;
4202552f7358SJed Brown           break;
4203552f7358SJed Brown         }
4204552f7358SJed Brown       }
4205552f7358SJed Brown     }
4206552f7358SJed Brown     joinSize = newJoinSize;
4207552f7358SJed Brown     i        = 1-i;
4208552f7358SJed Brown   }
4209552f7358SJed Brown   *numCoveredPoints = joinSize;
4210552f7358SJed Brown   *coveredPoints    = join[i];
42115f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]));
4212552f7358SJed Brown   PetscFunctionReturn(0);
4213552f7358SJed Brown }
4214552f7358SJed Brown 
4215552f7358SJed Brown /*@C
4216552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4217552f7358SJed Brown 
4218552f7358SJed Brown   Not Collective
4219552f7358SJed Brown 
4220552f7358SJed Brown   Input Parameters:
4221552f7358SJed Brown + dm - The DMPlex object
4222552f7358SJed Brown . numPoints - The number of input points for the join
4223552f7358SJed Brown - points - The input points
4224552f7358SJed Brown 
4225552f7358SJed Brown   Output Parameters:
4226552f7358SJed Brown + numCoveredPoints - The number of points in the join
4227552f7358SJed Brown - coveredPoints - The points in the join
4228552f7358SJed Brown 
42293813dfbdSMatthew G Knepley   Fortran Notes:
42303813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42313813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42323813dfbdSMatthew G Knepley 
42333813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42343813dfbdSMatthew G Knepley 
4235552f7358SJed Brown   Level: intermediate
4236552f7358SJed Brown 
4237552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet()
4238552f7358SJed Brown @*/
4239552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4240552f7358SJed Brown {
4241552f7358SJed Brown   PetscFunctionBegin;
4242552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4243d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4244d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4245d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
42465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4247d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4248552f7358SJed Brown   PetscFunctionReturn(0);
4249552f7358SJed Brown }
4250552f7358SJed Brown 
4251552f7358SJed Brown /*@C
4252552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4253552f7358SJed Brown 
4254552f7358SJed Brown   Not Collective
4255552f7358SJed Brown 
4256552f7358SJed Brown   Input Parameters:
4257552f7358SJed Brown + dm - The DMPlex object
4258552f7358SJed Brown . numPoints - The number of input points for the join
4259552f7358SJed Brown - points - The input points
4260552f7358SJed Brown 
4261552f7358SJed Brown   Output Parameters:
4262552f7358SJed Brown + numCoveredPoints - The number of points in the join
4263552f7358SJed Brown - coveredPoints - The points in the join
4264552f7358SJed Brown 
42653813dfbdSMatthew G Knepley   Fortran Notes:
42663813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42673813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42683813dfbdSMatthew G Knepley 
42693813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42703813dfbdSMatthew G Knepley 
4271552f7358SJed Brown   Level: intermediate
4272552f7358SJed Brown 
4273552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet()
4274552f7358SJed Brown @*/
4275552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4276552f7358SJed Brown {
4277552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4278552f7358SJed Brown   PetscInt      *offsets, **closures;
4279552f7358SJed Brown   PetscInt      *join[2];
4280552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
428124c766afSToby Isaac   PetscInt       p, d, c, m, ms;
4282552f7358SJed Brown 
4283552f7358SJed Brown   PetscFunctionBegin;
4284552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
428548bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
428648bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
428748bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4288552f7358SJed Brown 
42895f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
42905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(numPoints, &closures));
42915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
429224c766afSToby Isaac   ms      = mesh->maxSupportSize;
429324c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
42945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
42955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4296552f7358SJed Brown 
4297552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4298552f7358SJed Brown     PetscInt closureSize;
4299552f7358SJed Brown 
43005f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
43010d644c17SKarl Rupp 
4302552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
4303552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
4304552f7358SJed Brown       PetscInt pStart, pEnd, i;
4305552f7358SJed Brown 
43065f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4307552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
4308552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4309552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
4310552f7358SJed Brown           break;
4311552f7358SJed Brown         }
4312552f7358SJed Brown       }
4313552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
4314552f7358SJed Brown     }
43152c71b3e2SJacob 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);
4316552f7358SJed Brown   }
4317552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
4318552f7358SJed Brown     PetscInt dof;
4319552f7358SJed Brown 
4320552f7358SJed Brown     /* Copy in support of first point */
4321552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4322552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4323552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4324552f7358SJed Brown     }
4325552f7358SJed Brown     /* Check each successive cone */
4326552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4327552f7358SJed Brown       PetscInt newJoinSize = 0;
4328552f7358SJed Brown 
4329552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4330552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4331552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4332552f7358SJed Brown 
4333552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4334552f7358SJed Brown           if (point == join[i][m]) {
4335552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4336552f7358SJed Brown             break;
4337552f7358SJed Brown           }
4338552f7358SJed Brown         }
4339552f7358SJed Brown       }
4340552f7358SJed Brown       joinSize = newJoinSize;
4341552f7358SJed Brown       i        = 1-i;
4342552f7358SJed Brown     }
4343552f7358SJed Brown     if (joinSize) break;
4344552f7358SJed Brown   }
4345552f7358SJed Brown   *numCoveredPoints = joinSize;
4346552f7358SJed Brown   *coveredPoints    = join[i];
4347552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
43485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
4349552f7358SJed Brown   }
43505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(closures));
43515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]));
4353552f7358SJed Brown   PetscFunctionReturn(0);
4354552f7358SJed Brown }
4355552f7358SJed Brown 
4356552f7358SJed Brown /*@C
4357552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4358552f7358SJed Brown 
4359552f7358SJed Brown   Not Collective
4360552f7358SJed Brown 
4361552f7358SJed Brown   Input Parameters:
4362552f7358SJed Brown + dm - The DMPlex object
4363552f7358SJed Brown . numPoints - The number of input points for the meet
4364552f7358SJed Brown - points - The input points
4365552f7358SJed Brown 
4366552f7358SJed Brown   Output Parameters:
4367552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4368552f7358SJed Brown - coveredPoints - The points in the meet
4369552f7358SJed Brown 
4370552f7358SJed Brown   Level: intermediate
4371552f7358SJed Brown 
4372552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4373552f7358SJed Brown 
43743813dfbdSMatthew G Knepley   Fortran Notes:
43753813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43763813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43773813dfbdSMatthew G Knepley 
43783813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43793813dfbdSMatthew G Knepley 
4380552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin()
4381552f7358SJed Brown @*/
4382552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4383552f7358SJed Brown {
4384552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4385552f7358SJed Brown   PetscInt      *meet[2];
4386552f7358SJed Brown   PetscInt       meetSize, i = 0;
4387552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4388552f7358SJed Brown 
4389552f7358SJed Brown   PetscFunctionBegin;
4390552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4391*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4392*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4393064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
43945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]));
43955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]));
4396552f7358SJed Brown   /* Copy in cone of first point */
43975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
43985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4399552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4400552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4401552f7358SJed Brown   }
4402552f7358SJed Brown   /* Check each successive cone */
4403552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4404552f7358SJed Brown     PetscInt newMeetSize = 0;
4405552f7358SJed Brown 
44065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
44075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4408552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4409552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4410552f7358SJed Brown 
4411552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4412552f7358SJed Brown         if (point == meet[i][m]) {
4413552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4414552f7358SJed Brown           break;
4415552f7358SJed Brown         }
4416552f7358SJed Brown       }
4417552f7358SJed Brown     }
4418552f7358SJed Brown     meetSize = newMeetSize;
4419552f7358SJed Brown     i        = 1-i;
4420552f7358SJed Brown   }
4421552f7358SJed Brown   *numCoveringPoints = meetSize;
4422552f7358SJed Brown   *coveringPoints    = meet[i];
44235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]));
4424552f7358SJed Brown   PetscFunctionReturn(0);
4425552f7358SJed Brown }
4426552f7358SJed Brown 
4427552f7358SJed Brown /*@C
4428552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4429552f7358SJed Brown 
4430552f7358SJed Brown   Not Collective
4431552f7358SJed Brown 
4432552f7358SJed Brown   Input Parameters:
4433552f7358SJed Brown + dm - The DMPlex object
4434552f7358SJed Brown . numPoints - The number of input points for the meet
4435552f7358SJed Brown - points - The input points
4436552f7358SJed Brown 
4437552f7358SJed Brown   Output Parameters:
4438552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4439552f7358SJed Brown - coveredPoints - The points in the meet
4440552f7358SJed Brown 
4441552f7358SJed Brown   Level: intermediate
4442552f7358SJed Brown 
44433813dfbdSMatthew G Knepley   Fortran Notes:
44443813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44453813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44463813dfbdSMatthew G Knepley 
44473813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44483813dfbdSMatthew G Knepley 
4449552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin()
4450552f7358SJed Brown @*/
4451552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4452552f7358SJed Brown {
4453552f7358SJed Brown   PetscFunctionBegin;
4454552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4455d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4456d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4457d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
44585f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4459d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4460552f7358SJed Brown   PetscFunctionReturn(0);
4461552f7358SJed Brown }
4462552f7358SJed Brown 
4463552f7358SJed Brown /*@C
4464552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4465552f7358SJed Brown 
4466552f7358SJed Brown   Not Collective
4467552f7358SJed Brown 
4468552f7358SJed Brown   Input Parameters:
4469552f7358SJed Brown + dm - The DMPlex object
4470552f7358SJed Brown . numPoints - The number of input points for the meet
4471552f7358SJed Brown - points - The input points
4472552f7358SJed Brown 
4473552f7358SJed Brown   Output Parameters:
4474552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4475552f7358SJed Brown - coveredPoints - The points in the meet
4476552f7358SJed Brown 
4477552f7358SJed Brown   Level: intermediate
4478552f7358SJed Brown 
44793813dfbdSMatthew G Knepley   Fortran Notes:
44803813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44813813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44823813dfbdSMatthew G Knepley 
44833813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44843813dfbdSMatthew G Knepley 
4485552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin()
4486552f7358SJed Brown @*/
4487552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4488552f7358SJed Brown {
4489552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4490552f7358SJed Brown   PetscInt      *offsets, **closures;
4491552f7358SJed Brown   PetscInt      *meet[2];
4492552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
449324c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4494552f7358SJed Brown 
4495552f7358SJed Brown   PetscFunctionBegin;
4496552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4497*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4498*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4499064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4500552f7358SJed Brown 
45015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &height));
45025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(numPoints, &closures));
45035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
450424c766afSToby Isaac   mc      = mesh->maxConeSize;
450524c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
45065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
45075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4508552f7358SJed Brown 
4509552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4510552f7358SJed Brown     PetscInt closureSize;
4511552f7358SJed Brown 
45125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
45130d644c17SKarl Rupp 
4514552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4515552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4516552f7358SJed Brown       PetscInt pStart, pEnd, i;
4517552f7358SJed Brown 
45185f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4519552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4520552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4521552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4522552f7358SJed Brown           break;
4523552f7358SJed Brown         }
4524552f7358SJed Brown       }
4525552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4526552f7358SJed Brown     }
45272c71b3e2SJacob 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);
4528552f7358SJed Brown   }
4529552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4530552f7358SJed Brown     PetscInt dof;
4531552f7358SJed Brown 
4532552f7358SJed Brown     /* Copy in cone of first point */
4533552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4534552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4535552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4536552f7358SJed Brown     }
4537552f7358SJed Brown     /* Check each successive cone */
4538552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4539552f7358SJed Brown       PetscInt newMeetSize = 0;
4540552f7358SJed Brown 
4541552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4542552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4543552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4544552f7358SJed Brown 
4545552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4546552f7358SJed Brown           if (point == meet[i][m]) {
4547552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4548552f7358SJed Brown             break;
4549552f7358SJed Brown           }
4550552f7358SJed Brown         }
4551552f7358SJed Brown       }
4552552f7358SJed Brown       meetSize = newMeetSize;
4553552f7358SJed Brown       i        = 1-i;
4554552f7358SJed Brown     }
4555552f7358SJed Brown     if (meetSize) break;
4556552f7358SJed Brown   }
4557552f7358SJed Brown   *numCoveredPoints = meetSize;
4558552f7358SJed Brown   *coveredPoints    = meet[i];
4559552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
45605f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
4561552f7358SJed Brown   }
45625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(closures));
45635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]));
4565552f7358SJed Brown   PetscFunctionReturn(0);
4566552f7358SJed Brown }
4567552f7358SJed Brown 
45684e3744c5SMatthew G. Knepley /*@C
45694e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
45704e3744c5SMatthew G. Knepley 
45714e3744c5SMatthew G. Knepley   Not Collective
45724e3744c5SMatthew G. Knepley 
45734e3744c5SMatthew G. Knepley   Input Parameters:
45744e3744c5SMatthew G. Knepley + dmA - A DMPlex object
45754e3744c5SMatthew G. Knepley - dmB - A DMPlex object
45764e3744c5SMatthew G. Knepley 
45774e3744c5SMatthew G. Knepley   Output Parameters:
45784e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
45794e3744c5SMatthew G. Knepley 
45804e3744c5SMatthew G. Knepley   Level: intermediate
45814e3744c5SMatthew G. Knepley 
45824e3744c5SMatthew G. Knepley   Notes:
45834e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
45844e3744c5SMatthew G. Knepley 
45854e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone()
45864e3744c5SMatthew G. Knepley @*/
45874e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
45884e3744c5SMatthew G. Knepley {
45894e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
45904e3744c5SMatthew G. Knepley 
45914e3744c5SMatthew G. Knepley   PetscFunctionBegin;
45924e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
45934e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4594*dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
45954e3744c5SMatthew G. Knepley 
45964e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
45975f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dmA, &depth));
45985f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dmB, &depthB));
45994e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
46005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dmA, &pStart,  &pEnd));
46015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dmB, &pStartB, &pEndB));
46024e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
46034e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
46044e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
46054e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
46064e3744c5SMatthew G. Knepley 
46075f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dmA, p, &coneSize));
46085f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dmA, p, &cone));
46095f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeOrientation(dmA, p, &ornt));
46105f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dmB, p, &coneSizeB));
46115f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dmB, p, &coneB));
46125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeOrientation(dmB, p, &orntB));
46134e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
46144e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
46154e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
46164e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
46174e3744c5SMatthew G. Knepley     }
46185f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupportSize(dmA, p, &supportSize));
46195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupport(dmA, p, &support));
46205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupportSize(dmB, p, &supportSizeB));
46215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupport(dmB, p, &supportB));
46224e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
46234e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
46244e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
46254e3744c5SMatthew G. Knepley     }
46264e3744c5SMatthew G. Knepley   }
46274e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
46284e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
46294e3744c5SMatthew G. Knepley }
46304e3744c5SMatthew G. Knepley 
46317cd05799SMatthew G. Knepley /*@C
46327cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
46337cd05799SMatthew G. Knepley 
46347cd05799SMatthew G. Knepley   Not Collective
46357cd05799SMatthew G. Knepley 
46367cd05799SMatthew G. Knepley   Input Parameters:
46377cd05799SMatthew G. Knepley + dm         - The DMPlex
46387cd05799SMatthew G. Knepley . cellDim    - The cell dimension
46397cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
46407cd05799SMatthew G. Knepley 
46417cd05799SMatthew G. Knepley   Output Parameters:
46427cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
46437cd05799SMatthew G. Knepley 
46447cd05799SMatthew G. Knepley   Level: developer
46457cd05799SMatthew G. Knepley 
46467cd05799SMatthew G. Knepley   Notes:
46477cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
46487cd05799SMatthew G. Knepley 
46497cd05799SMatthew G. Knepley .seealso: DMPlexGetCone()
46507cd05799SMatthew G. Knepley @*/
465118ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4652a6dfd86eSKarl Rupp {
465382f516ccSBarry Smith   MPI_Comm       comm;
4654552f7358SJed Brown 
4655552f7358SJed Brown   PetscFunctionBegin;
46565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
4657*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices,4);
4658552f7358SJed Brown   switch (cellDim) {
4659552f7358SJed Brown   case 0:
4660552f7358SJed Brown     *numFaceVertices = 0;
4661552f7358SJed Brown     break;
4662552f7358SJed Brown   case 1:
4663552f7358SJed Brown     *numFaceVertices = 1;
4664552f7358SJed Brown     break;
4665552f7358SJed Brown   case 2:
4666552f7358SJed Brown     switch (numCorners) {
466719436ca2SJed Brown     case 3: /* triangle */
466819436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4669552f7358SJed Brown       break;
467019436ca2SJed Brown     case 4: /* quadrilateral */
467119436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4672552f7358SJed Brown       break;
467319436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
467419436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4675552f7358SJed Brown       break;
467619436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
467719436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4678552f7358SJed Brown       break;
4679552f7358SJed Brown     default:
468098921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4681552f7358SJed Brown     }
4682552f7358SJed Brown     break;
4683552f7358SJed Brown   case 3:
4684552f7358SJed Brown     switch (numCorners) {
468519436ca2SJed Brown     case 4: /* tetradehdron */
468619436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4687552f7358SJed Brown       break;
468819436ca2SJed Brown     case 6: /* tet cohesive cells */
468919436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4690552f7358SJed Brown       break;
469119436ca2SJed Brown     case 8: /* hexahedron */
469219436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4693552f7358SJed Brown       break;
469419436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
469519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4696552f7358SJed Brown       break;
469719436ca2SJed Brown     case 10: /* quadratic tetrahedron */
469819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4699552f7358SJed Brown       break;
470019436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
470119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4702552f7358SJed Brown       break;
470319436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
470419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4705552f7358SJed Brown       break;
470619436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
470719436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4708552f7358SJed Brown       break;
4709552f7358SJed Brown     default:
471098921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4711552f7358SJed Brown     }
4712552f7358SJed Brown     break;
4713552f7358SJed Brown   default:
471498921bdaSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim);
4715552f7358SJed Brown   }
4716552f7358SJed Brown   PetscFunctionReturn(0);
4717552f7358SJed Brown }
4718552f7358SJed Brown 
4719552f7358SJed Brown /*@
4720aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4721552f7358SJed Brown 
4722552f7358SJed Brown   Not Collective
4723552f7358SJed Brown 
4724aa50250dSMatthew G. Knepley   Input Parameter:
4725552f7358SJed Brown . dm    - The DMPlex object
4726552f7358SJed Brown 
4727aa50250dSMatthew G. Knepley   Output Parameter:
4728aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4729552f7358SJed Brown 
4730552f7358SJed Brown   Level: developer
4731552f7358SJed Brown 
4732dc287ab2SVaclav Hapla .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(),
4733aa50250dSMatthew G. Knepley @*/
4734aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4735aa50250dSMatthew G. Knepley {
4736aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4737aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4738aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4739c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4740aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4741aa50250dSMatthew G. Knepley }
4742aa50250dSMatthew G. Knepley 
4743aa50250dSMatthew G. Knepley /*@
4744aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4745aa50250dSMatthew G. Knepley 
4746aa50250dSMatthew G. Knepley   Not Collective
4747aa50250dSMatthew G. Knepley 
4748aa50250dSMatthew G. Knepley   Input Parameter:
4749aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4750aa50250dSMatthew G. Knepley 
4751aa50250dSMatthew G. Knepley   Output Parameter:
4752aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4753aa50250dSMatthew G. Knepley 
4754aa50250dSMatthew G. Knepley   Level: developer
4755552f7358SJed Brown 
4756b1bb481bSMatthew Knepley   Notes:
4757b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4758dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4759dc287ab2SVaclav Hapla   An empty mesh gives -1.
4760b1bb481bSMatthew Knepley 
4761dc287ab2SVaclav Hapla .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize()
4762552f7358SJed Brown @*/
4763552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4764552f7358SJed Brown {
4765aa50250dSMatthew G. Knepley   DMLabel        label;
4766aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4767552f7358SJed Brown 
4768552f7358SJed Brown   PetscFunctionBegin;
4769552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4770*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
47715f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &label));
47725f80ce2aSJacob Faibussowitsch   if (label) CHKERRQ(DMLabelGetNumValues(label, &d));
4773552f7358SJed Brown   *depth = d-1;
4774552f7358SJed Brown   PetscFunctionReturn(0);
4775552f7358SJed Brown }
4776552f7358SJed Brown 
4777552f7358SJed Brown /*@
4778552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4779552f7358SJed Brown 
4780552f7358SJed Brown   Not Collective
4781552f7358SJed Brown 
4782552f7358SJed Brown   Input Parameters:
4783552f7358SJed Brown + dm           - The DMPlex object
4784552f7358SJed Brown - stratumValue - The requested depth
4785552f7358SJed Brown 
4786552f7358SJed Brown   Output Parameters:
4787552f7358SJed Brown + start - The first point at this depth
4788552f7358SJed Brown - end   - One beyond the last point at this depth
4789552f7358SJed Brown 
4790647867b2SJed Brown   Notes:
4791647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4792647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4793647867b2SJed Brown   higher dimension, e.g., "edges".
4794647867b2SJed Brown 
4795552f7358SJed Brown   Level: developer
4796552f7358SJed Brown 
4797dc287ab2SVaclav Hapla .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate()
4798552f7358SJed Brown @*/
47990adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
48000adebc6cSBarry Smith {
4801aa50250dSMatthew G. Knepley   DMLabel        label;
480263d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4803552f7358SJed Brown 
4804552f7358SJed Brown   PetscFunctionBegin;
4805552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4806*dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4807*dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
48090d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
481063d1a920SMatthew G. Knepley   if (stratumValue < 0) {
481163d1a920SMatthew G. Knepley     if (start) *start = pStart;
481263d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
481363d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4814552f7358SJed Brown   }
48155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &label));
481628b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetStratumBounds(label, stratumValue, start, end));
4818552f7358SJed Brown   PetscFunctionReturn(0);
4819552f7358SJed Brown }
4820552f7358SJed Brown 
4821552f7358SJed Brown /*@
4822552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4823552f7358SJed Brown 
4824552f7358SJed Brown   Not Collective
4825552f7358SJed Brown 
4826552f7358SJed Brown   Input Parameters:
4827552f7358SJed Brown + dm           - The DMPlex object
4828552f7358SJed Brown - stratumValue - The requested height
4829552f7358SJed Brown 
4830552f7358SJed Brown   Output Parameters:
4831552f7358SJed Brown + start - The first point at this height
4832552f7358SJed Brown - end   - One beyond the last point at this height
4833552f7358SJed Brown 
4834647867b2SJed Brown   Notes:
4835647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4836647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4837647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4838647867b2SJed Brown 
4839552f7358SJed Brown   Level: developer
4840552f7358SJed Brown 
48413dc9a465SVaclav Hapla .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight()
4842552f7358SJed Brown @*/
48430adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
48440adebc6cSBarry Smith {
4845aa50250dSMatthew G. Knepley   DMLabel        label;
484663d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4847552f7358SJed Brown 
4848552f7358SJed Brown   PetscFunctionBegin;
4849552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4850*dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4851*dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
48530d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
485463d1a920SMatthew G. Knepley   if (stratumValue < 0) {
485563d1a920SMatthew G. Knepley     if (start) *start = pStart;
485663d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
485763d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4858552f7358SJed Brown   }
48595f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &label));
486028b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48615f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetNumValues(label, &depth));
48625f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end));
4863552f7358SJed Brown   PetscFunctionReturn(0);
4864552f7358SJed Brown }
4865552f7358SJed Brown 
4866ba2698f1SMatthew G. Knepley /*@
4867ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4868ba2698f1SMatthew G. Knepley 
4869ba2698f1SMatthew G. Knepley   Not Collective
4870ba2698f1SMatthew G. Knepley 
4871d8d19677SJose E. Roman   Input Parameters:
4872ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4873ba2698f1SMatthew G. Knepley - point - The point
4874ba2698f1SMatthew G. Knepley 
4875ba2698f1SMatthew G. Knepley   Output Parameter:
4876ba2698f1SMatthew G. Knepley . depth - The depth of the point
4877ba2698f1SMatthew G. Knepley 
4878ba2698f1SMatthew G. Knepley   Level: intermediate
4879ba2698f1SMatthew G. Knepley 
48803dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight()
4881ba2698f1SMatthew G. Knepley @*/
4882ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4883ba2698f1SMatthew G. Knepley {
4884ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4885ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
488640a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
48875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetValue(dm->depthLabel, point, depth));
4888ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4889ba2698f1SMatthew G. Knepley }
4890ba2698f1SMatthew G. Knepley 
4891ba2698f1SMatthew G. Knepley /*@
48920c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
48930c0a32dcSVaclav Hapla 
48940c0a32dcSVaclav Hapla   Not Collective
48950c0a32dcSVaclav Hapla 
4896d8d19677SJose E. Roman   Input Parameters:
48970c0a32dcSVaclav Hapla + dm    - The DMPlex object
48980c0a32dcSVaclav Hapla - point - The point
48990c0a32dcSVaclav Hapla 
49000c0a32dcSVaclav Hapla   Output Parameter:
49010c0a32dcSVaclav Hapla . height - The height of the point
49020c0a32dcSVaclav Hapla 
49030c0a32dcSVaclav Hapla   Level: intermediate
49040c0a32dcSVaclav Hapla 
49053dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth()
49060c0a32dcSVaclav Hapla @*/
49070c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
49080c0a32dcSVaclav Hapla {
49090c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
49100c0a32dcSVaclav Hapla 
49110c0a32dcSVaclav Hapla   PetscFunctionBegin;
49120c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49130c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
49145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetNumValues(dm->depthLabel, &n));
49155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetValue(dm->depthLabel, point, &pDepth));
49160c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
49170c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
49180c0a32dcSVaclav Hapla }
49190c0a32dcSVaclav Hapla 
49200c0a32dcSVaclav Hapla /*@
4921ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4922ba2698f1SMatthew G. Knepley 
4923ba2698f1SMatthew G. Knepley   Not Collective
4924ba2698f1SMatthew G. Knepley 
4925ba2698f1SMatthew G. Knepley   Input Parameter:
4926ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4927ba2698f1SMatthew G. Knepley 
4928ba2698f1SMatthew G. Knepley   Output Parameter:
4929ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4930ba2698f1SMatthew G. Knepley 
4931412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4932412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4933412e9a14SMatthew G. Knepley 
4934ba2698f1SMatthew G. Knepley   Level: developer
4935ba2698f1SMatthew G. Knepley 
4936dc287ab2SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel()
4937ba2698f1SMatthew G. Knepley @*/
4938ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4939ba2698f1SMatthew G. Knepley {
4940ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4941ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4942ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
49435f80ce2aSJacob Faibussowitsch   if (!dm->celltypeLabel) CHKERRQ(DMPlexComputeCellTypes(dm));
4944ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4945ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4946ba2698f1SMatthew G. Knepley }
4947ba2698f1SMatthew G. Knepley 
4948ba2698f1SMatthew G. Knepley /*@
4949ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4950ba2698f1SMatthew G. Knepley 
4951ba2698f1SMatthew G. Knepley   Not Collective
4952ba2698f1SMatthew G. Knepley 
4953d8d19677SJose E. Roman   Input Parameters:
4954ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4955ba2698f1SMatthew G. Knepley - cell - The cell
4956ba2698f1SMatthew G. Knepley 
4957ba2698f1SMatthew G. Knepley   Output Parameter:
4958ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4959ba2698f1SMatthew G. Knepley 
4960ba2698f1SMatthew G. Knepley   Level: intermediate
4961ba2698f1SMatthew G. Knepley 
4962ba2698f1SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth()
4963ba2698f1SMatthew G. Knepley @*/
4964ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4965ba2698f1SMatthew G. Knepley {
4966ba2698f1SMatthew G. Knepley   DMLabel        label;
4967ba2698f1SMatthew G. Knepley   PetscInt       ct;
4968ba2698f1SMatthew G. Knepley 
4969ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4970ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4971ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
49725f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellTypeLabel(dm, &label));
49735f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetValue(label, cell, &ct));
49742c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell);
4975ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
4976ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4977ba2698f1SMatthew G. Knepley }
4978ba2698f1SMatthew G. Knepley 
4979412e9a14SMatthew G. Knepley /*@
4980412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
4981412e9a14SMatthew G. Knepley 
4982412e9a14SMatthew G. Knepley   Not Collective
4983412e9a14SMatthew G. Knepley 
4984412e9a14SMatthew G. Knepley   Input Parameters:
4985412e9a14SMatthew G. Knepley + dm   - The DMPlex object
4986412e9a14SMatthew G. Knepley . cell - The cell
4987412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
4988412e9a14SMatthew G. Knepley 
4989412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
4990412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
4991412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
4992412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
4993412e9a14SMatthew G. Knepley 
4994412e9a14SMatthew G. Knepley   Level: advanced
4995412e9a14SMatthew G. Knepley 
4996412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel()
4997412e9a14SMatthew G. Knepley @*/
4998412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
4999412e9a14SMatthew G. Knepley {
5000412e9a14SMatthew G. Knepley   DMLabel        label;
5001412e9a14SMatthew G. Knepley 
5002412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5003412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50045f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellTypeLabel(dm, &label));
50055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelSetValue(label, cell, celltype));
5006412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
5007412e9a14SMatthew G. Knepley }
5008412e9a14SMatthew G. Knepley 
50090adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
50100adebc6cSBarry Smith {
5011efe440bfSMatthew G. Knepley   PetscSection   section, s;
5012efe440bfSMatthew G. Knepley   Mat            m;
50133e922f36SToby Isaac   PetscInt       maxHeight;
5014552f7358SJed Brown 
5015552f7358SJed Brown   PetscFunctionBegin;
50165f80ce2aSJacob Faibussowitsch   CHKERRQ(DMClone(dm, cdm));
50175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
50185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
50195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
50205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetLocalSection(*cdm, section));
50215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&section));
50225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF, &s));
50235f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_SELF, &m));
50245f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDefaultConstraints(*cdm, s, m, NULL));
50255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&s));
50265f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&m));
50278f4c458bSMatthew G. Knepley 
50285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetNumFields(*cdm, 1));
50295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateDS(*cdm));
5030552f7358SJed Brown   PetscFunctionReturn(0);
5031552f7358SJed Brown }
5032552f7358SJed Brown 
5033f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5034f19dbd58SToby Isaac {
5035f19dbd58SToby Isaac   Vec            coordsLocal;
5036f19dbd58SToby Isaac   DM             coordsDM;
5037f19dbd58SToby Isaac 
5038f19dbd58SToby Isaac   PetscFunctionBegin;
5039f19dbd58SToby Isaac   *field = NULL;
50405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm,&coordsLocal));
50415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm,&coordsDM));
5042f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
50435f80ce2aSJacob Faibussowitsch     CHKERRQ(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5044f19dbd58SToby Isaac   }
5045f19dbd58SToby Isaac   PetscFunctionReturn(0);
5046f19dbd58SToby Isaac }
5047f19dbd58SToby Isaac 
50487cd05799SMatthew G. Knepley /*@C
50497cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
50507cd05799SMatthew G. Knepley 
50517cd05799SMatthew G. Knepley   Not Collective
50527cd05799SMatthew G. Knepley 
50537cd05799SMatthew G. Knepley   Input Parameters:
50547cd05799SMatthew G. Knepley . dm        - The DMPlex object
50557cd05799SMatthew G. Knepley 
50567cd05799SMatthew G. Knepley   Output Parameter:
50577cd05799SMatthew G. Knepley . section - The PetscSection object
50587cd05799SMatthew G. Knepley 
50597cd05799SMatthew G. Knepley   Level: developer
50607cd05799SMatthew G. Knepley 
50617cd05799SMatthew G. Knepley .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations()
50627cd05799SMatthew G. Knepley @*/
50630adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50640adebc6cSBarry Smith {
5065552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5066552f7358SJed Brown 
5067552f7358SJed Brown   PetscFunctionBegin;
5068552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5069552f7358SJed Brown   if (section) *section = mesh->coneSection;
5070552f7358SJed Brown   PetscFunctionReturn(0);
5071552f7358SJed Brown }
5072552f7358SJed Brown 
50737cd05799SMatthew G. Knepley /*@C
50747cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
50757cd05799SMatthew G. Knepley 
50767cd05799SMatthew G. Knepley   Not Collective
50777cd05799SMatthew G. Knepley 
50787cd05799SMatthew G. Knepley   Input Parameters:
50797cd05799SMatthew G. Knepley . dm        - The DMPlex object
50807cd05799SMatthew G. Knepley 
50817cd05799SMatthew G. Knepley   Output Parameter:
50827cd05799SMatthew G. Knepley . section - The PetscSection object
50837cd05799SMatthew G. Knepley 
50847cd05799SMatthew G. Knepley   Level: developer
50857cd05799SMatthew G. Knepley 
50867cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
50877cd05799SMatthew G. Knepley @*/
50888cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
50898cb4d582SMatthew G. Knepley {
50908cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
50918cb4d582SMatthew G. Knepley 
50928cb4d582SMatthew G. Knepley   PetscFunctionBegin;
50938cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50948cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
50958cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
50968cb4d582SMatthew G. Knepley }
50978cb4d582SMatthew G. Knepley 
50987cd05799SMatthew G. Knepley /*@C
50997cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
51007cd05799SMatthew G. Knepley 
51017cd05799SMatthew G. Knepley   Not Collective
51027cd05799SMatthew G. Knepley 
51037cd05799SMatthew G. Knepley   Input Parameters:
51047cd05799SMatthew G. Knepley . dm        - The DMPlex object
51057cd05799SMatthew G. Knepley 
51067cd05799SMatthew G. Knepley   Output Parameter:
51077cd05799SMatthew G. Knepley . cones - The cone for each point
51087cd05799SMatthew G. Knepley 
51097cd05799SMatthew G. Knepley   Level: developer
51107cd05799SMatthew G. Knepley 
51117cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
51127cd05799SMatthew G. Knepley @*/
5113a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5114a6dfd86eSKarl Rupp {
5115552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5116552f7358SJed Brown 
5117552f7358SJed Brown   PetscFunctionBegin;
5118552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5119552f7358SJed Brown   if (cones) *cones = mesh->cones;
5120552f7358SJed Brown   PetscFunctionReturn(0);
5121552f7358SJed Brown }
5122552f7358SJed Brown 
51237cd05799SMatthew G. Knepley /*@C
51247cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
51257cd05799SMatthew G. Knepley 
51267cd05799SMatthew G. Knepley   Not Collective
51277cd05799SMatthew G. Knepley 
51287cd05799SMatthew G. Knepley   Input Parameters:
51297cd05799SMatthew G. Knepley . dm        - The DMPlex object
51307cd05799SMatthew G. Knepley 
51317cd05799SMatthew G. Knepley   Output Parameter:
5132b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
51337cd05799SMatthew G. Knepley 
51347cd05799SMatthew G. Knepley   Level: developer
51357cd05799SMatthew G. Knepley 
5136b5a892a1SMatthew G. Knepley   Notes:
5137b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5138b5a892a1SMatthew G. Knepley 
5139b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5140b5a892a1SMatthew G. Knepley 
5141b5a892a1SMatthew G. Knepley .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation()
51427cd05799SMatthew G. Knepley @*/
5143a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5144a6dfd86eSKarl Rupp {
5145552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5146552f7358SJed Brown 
5147552f7358SJed Brown   PetscFunctionBegin;
5148552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5149552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5150552f7358SJed Brown   PetscFunctionReturn(0);
5151552f7358SJed Brown }
5152552f7358SJed Brown 
5153552f7358SJed Brown /******************************** FEM Support **********************************/
5154552f7358SJed Brown 
51559e8305c2SJed Brown /*
51569e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
51579e8305c2SJed Brown  representing a line in the section.
51589e8305c2SJed Brown */
51599e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
51609e8305c2SJed Brown {
51619e8305c2SJed Brown   PetscFunctionBeginHot;
51625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldComponents(section, field, Nc));
5163a433471fSStefano Zampini   if (line < 0) {
5164a433471fSStefano Zampini     *k = 0;
5165a433471fSStefano Zampini     *Nc = 0;
5166a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
51679e8305c2SJed Brown     *k = 1;
51689e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
51699e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
51705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldDof(section, line, field, k));
51719e8305c2SJed Brown     *k = *k / *Nc + 1;
51729e8305c2SJed Brown   }
51739e8305c2SJed Brown   PetscFunctionReturn(0);
51749e8305c2SJed Brown }
51759e8305c2SJed Brown 
5176a4355906SMatthew Knepley /*@
5177bc1eb3faSJed Brown 
5178bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5179bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
51801bb6d2a8SBarry Smith   section provided (or the section of the DM).
5181a4355906SMatthew Knepley 
5182a4355906SMatthew Knepley   Input Parameters:
5183a4355906SMatthew Knepley + dm      - The DM
5184a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5185a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5186a4355906SMatthew Knepley 
5187a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5188a4355906SMatthew Knepley   degree of the basis.
5189a4355906SMatthew Knepley 
5190bc1eb3faSJed Brown   Example:
5191bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5192bc1eb3faSJed Brown .vb
5193bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5194bc1eb3faSJed Brown 
5195bc1eb3faSJed Brown   v4 -- e6 -- v3
5196bc1eb3faSJed Brown   |           |
5197bc1eb3faSJed Brown   e7    c0    e8
5198bc1eb3faSJed Brown   |           |
5199bc1eb3faSJed Brown   v1 -- e5 -- v2
5200bc1eb3faSJed Brown .ve
5201bc1eb3faSJed Brown 
5202bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5203bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5204bc1eb3faSJed Brown .vb
5205bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5206bc1eb3faSJed Brown     v1 -> [4]
5207bc1eb3faSJed Brown     ...
5208bc1eb3faSJed Brown     e5 -> [8, 9]
5209bc1eb3faSJed Brown .ve
5210bc1eb3faSJed Brown 
5211bc1eb3faSJed Brown   which corresponds to the dofs
5212bc1eb3faSJed Brown .vb
5213bc1eb3faSJed Brown     6   10  11  7
5214bc1eb3faSJed Brown     13  2   3   15
5215bc1eb3faSJed Brown     12  0   1   14
5216bc1eb3faSJed Brown     4   8   9   5
5217bc1eb3faSJed Brown .ve
5218bc1eb3faSJed Brown 
5219bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5220bc1eb3faSJed Brown .vb
5221bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5222bc1eb3faSJed Brown .ve
5223bc1eb3faSJed Brown 
5224bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5225bc1eb3faSJed Brown .vb
5226bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5227bc1eb3faSJed Brown .ve
5228bc1eb3faSJed Brown 
5229a4355906SMatthew Knepley   Level: developer
5230a4355906SMatthew Knepley 
52319df75925SJed Brown .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection()
5232a4355906SMatthew Knepley @*/
5233bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
52343194fc30SMatthew G. Knepley {
52357391a63aSMatthew G. Knepley   DMLabel        label;
5236bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
52379e8305c2SJed Brown   PetscBool      vertexchart;
52383194fc30SMatthew G. Knepley 
52393194fc30SMatthew G. Knepley   PetscFunctionBegin;
52405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
5241a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5242a433471fSStefano Zampini   if (point < 0) {
5243a433471fSStefano Zampini     PetscInt sStart,sEnd;
5244a433471fSStefano Zampini 
52455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5246a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
5247a433471fSStefano Zampini   }
52485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &label));
52495f80ce2aSJacob Faibussowitsch   if (point >= 0) CHKERRQ(DMLabelGetValue(label, point, &depth));
52505f80ce2aSJacob Faibussowitsch   if (!section) CHKERRQ(DMGetLocalSection(dm, &section));
52517391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
52527391a63aSMatthew G. Knepley   else if  (depth == dim) {
52537391a63aSMatthew G. Knepley     const PetscInt *cone;
52547391a63aSMatthew G. Knepley 
52555f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, point, &cone));
5256d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5257d4e6627bSStefano Zampini     else if (dim == 3) {
5258d4e6627bSStefano Zampini       const PetscInt *cone2;
52595f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, cone[0], &cone2));
5260d4e6627bSStefano Zampini       eStart = cone2[0];
526198921bdaSJacob 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);
52622c71b3e2SJacob 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);
52639e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
52649e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
52655f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd));
52665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(section,&cStart,&cEnd));
5267796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5268796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5269796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
52709e8305c2SJed Brown   }
52715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &Nf));
5272bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
5273bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5274bb197d40SJed Brown     PetscInt *perm;
5275bb197d40SJed Brown 
52763194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
52775f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5278bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
52793194fc30SMatthew G. Knepley     }
52805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(size, &perm));
52813194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5282bb197d40SJed Brown       switch (d) {
5283babf31e0SJed Brown       case 1:
52845f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5285babf31e0SJed Brown         /*
5286babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5287babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5288babf31e0SJed Brown          */
5289babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
5290babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
5291babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
5292babf31e0SJed Brown         foffset = offset;
5293babf31e0SJed Brown         break;
529489eabcffSMatthew G. Knepley       case 2:
52953194fc30SMatthew 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} */
52965f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
52973194fc30SMatthew G. Knepley         /* The SEM order is
52983194fc30SMatthew G. Knepley 
52993194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
530089eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
53013194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
53023194fc30SMatthew G. Knepley          */
53033194fc30SMatthew G. Knepley         {
53043194fc30SMatthew G. Knepley           const PetscInt of   = 0;
53053194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
53063194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
53073194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
53083194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
53093194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
53103194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
53113194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
53123194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
53133194fc30SMatthew G. Knepley           PetscInt       o;
53143194fc30SMatthew G. Knepley 
53153194fc30SMatthew G. Knepley           /* bottom */
53163194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
53173194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53183194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
53193194fc30SMatthew G. Knepley           /* middle */
53203194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
53213194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
53223194fc30SMatthew 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;
53233194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
53243194fc30SMatthew G. Knepley           }
53253194fc30SMatthew G. Knepley           /* top */
53263194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
53273194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53283194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
53293194fc30SMatthew G. Knepley           foffset = offset;
53303194fc30SMatthew G. Knepley         }
533189eabcffSMatthew G. Knepley         break;
533289eabcffSMatthew G. Knepley       case 3:
533389eabcffSMatthew G. Knepley         /* The original hex closure is
533489eabcffSMatthew G. Knepley 
533589eabcffSMatthew G. Knepley          {c,
533689eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
533789eabcffSMatthew 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,
533889eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
533989eabcffSMatthew G. Knepley          */
53405f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
534189eabcffSMatthew G. Knepley         /* The SEM order is
534289eabcffSMatthew G. Knepley          Bottom Slice
534389eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
534489eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
534589eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
534689eabcffSMatthew G. Knepley 
534789eabcffSMatthew G. Knepley          Middle Slice (j)
534889eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
534989eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
535089eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
535189eabcffSMatthew G. Knepley 
535289eabcffSMatthew G. Knepley          Top Slice
535389eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
535489eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
535589eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
535689eabcffSMatthew G. Knepley          */
535789eabcffSMatthew G. Knepley         {
535889eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
535989eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
536089eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
536189eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
536289eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
536389eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
536489eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
536589eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
536689eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
536789eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
536889eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
536989eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
537089eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
537189eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
537289eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
537389eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
537489eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
537589eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
537689eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
537789eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
537889eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
537989eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
538089eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
538189eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
538289eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
538389eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
538489eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
538589eabcffSMatthew G. Knepley           PetscInt       o, n;
538689eabcffSMatthew G. Knepley 
538789eabcffSMatthew G. Knepley           /* Bottom Slice */
538889eabcffSMatthew G. Knepley           /*   bottom */
538989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
539089eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
539189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
539289eabcffSMatthew G. Knepley           /*   middle */
539389eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
539489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5395316b7f87SMax 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;}
539689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
53973194fc30SMatthew G. Knepley           }
539889eabcffSMatthew G. Knepley           /*   top */
539989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
540089eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
540189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
540289eabcffSMatthew G. Knepley 
540389eabcffSMatthew G. Knepley           /* Middle Slice */
540489eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
540589eabcffSMatthew G. Knepley             /*   bottom */
540689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
540789eabcffSMatthew 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;
540889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
540989eabcffSMatthew G. Knepley             /*   middle */
541089eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
541189eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
541289eabcffSMatthew 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;
541389eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
541489eabcffSMatthew G. Knepley             }
541589eabcffSMatthew G. Knepley             /*   top */
541689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
541789eabcffSMatthew 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;
541889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
541989eabcffSMatthew G. Knepley           }
542089eabcffSMatthew G. Knepley 
542189eabcffSMatthew G. Knepley           /* Top Slice */
542289eabcffSMatthew G. Knepley           /*   bottom */
542389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
542489eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
542589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
542689eabcffSMatthew G. Knepley           /*   middle */
542789eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
542889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
542989eabcffSMatthew 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;
543089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
543189eabcffSMatthew G. Knepley           }
543289eabcffSMatthew G. Knepley           /*   top */
543389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
543489eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
543589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
543689eabcffSMatthew G. Knepley 
543789eabcffSMatthew G. Knepley           foffset = offset;
543889eabcffSMatthew G. Knepley         }
543989eabcffSMatthew G. Knepley         break;
544098921bdaSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d);
544189eabcffSMatthew G. Knepley       }
544289eabcffSMatthew G. Knepley     }
54432c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size);
54443194fc30SMatthew G. Knepley     /* Check permutation */
54453194fc30SMatthew G. Knepley     {
54463194fc30SMatthew G. Knepley       PetscInt *check;
54473194fc30SMatthew G. Knepley 
54485f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(size, &check));
54492c71b3e2SJacob 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]);}
54503194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54512c71b3e2SJacob Faibussowitsch       for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);}
54525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(check));
54533194fc30SMatthew G. Knepley     }
54545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm));
5455a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5456a05c9aa3SJed Brown       PetscInt *loc_perm;
54575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(size*2, &loc_perm));
5458a05c9aa3SJed Brown       for (PetscInt i=0; i<size; i++) {
5459a05c9aa3SJed Brown         loc_perm[i] = perm[i];
5460a05c9aa3SJed Brown         loc_perm[size+i] = size + perm[i];
5461a05c9aa3SJed Brown       }
54625f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm));
5463a05c9aa3SJed Brown     }
5464bb197d40SJed Brown   }
54653194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
54663194fc30SMatthew G. Knepley }
54673194fc30SMatthew G. Knepley 
5468e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5469e071409bSToby Isaac {
5470e071409bSToby Isaac   PetscDS        prob;
5471e071409bSToby Isaac   PetscInt       depth, Nf, h;
5472e071409bSToby Isaac   DMLabel        label;
5473e071409bSToby Isaac 
5474e071409bSToby Isaac   PetscFunctionBeginHot;
54755f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDS(dm, &prob));
5476e071409bSToby Isaac   Nf      = prob->Nf;
5477e071409bSToby Isaac   label   = dm->depthLabel;
5478e071409bSToby Isaac   *dspace = NULL;
5479e071409bSToby Isaac   if (field < Nf) {
5480e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5481e071409bSToby Isaac 
5482e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5483e071409bSToby Isaac       PetscDualSpace dsp;
5484e071409bSToby Isaac 
54855f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFEGetDualSpace((PetscFE)disc,&dsp));
54865f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetNumValues(label,&depth));
54875f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValue(label,point,&h));
5488e071409bSToby Isaac       h    = depth - 1 - h;
5489e071409bSToby Isaac       if (h) {
54905f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscDualSpaceGetHeightSubspace(dsp,h,dspace));
5491e071409bSToby Isaac       } else {
5492e071409bSToby Isaac         *dspace = dsp;
5493e071409bSToby Isaac       }
5494e071409bSToby Isaac     }
5495e071409bSToby Isaac   }
5496e071409bSToby Isaac   PetscFunctionReturn(0);
5497e071409bSToby Isaac }
5498e071409bSToby Isaac 
54999fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5500a6dfd86eSKarl Rupp {
5501552f7358SJed Brown   PetscScalar    *array, *vArray;
5502d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
55031a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5504552f7358SJed Brown 
55051b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
55065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd));
55075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, point, &numPoints));
55085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCone(dm, point, &cone));
55095f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeOrientation(dm, point, &coneO));
55103f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
55119df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
55129df71ca4SMatthew G. Knepley       PetscInt dof;
5513d9917b9dSMatthew G. Knepley 
55145f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section, point, &dof));
55159df71ca4SMatthew G. Knepley       size += dof;
55169df71ca4SMatthew G. Knepley     }
55179df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
55189df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
55192a3aaacfSMatthew G. Knepley       PetscInt       dof;
55205a1bb5cfSMatthew G. Knepley 
55215a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
55225f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section, cp, &dof));
55235a1bb5cfSMatthew G. Knepley       size += dof;
55245a1bb5cfSMatthew G. Knepley     }
55253f7cbbe7SMatthew G. Knepley     if (!values) {
55263f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
55273f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
55283f7cbbe7SMatthew G. Knepley     }
55295f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5530982e9ed1SMatthew G. Knepley   } else {
5531982e9ed1SMatthew G. Knepley     array = *values;
5532982e9ed1SMatthew G. Knepley   }
55339df71ca4SMatthew G. Knepley   size = 0;
55345f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(v, &vArray));
55359df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
55369df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
55379df71ca4SMatthew G. Knepley     PetscScalar *varr;
5538d9917b9dSMatthew G. Knepley 
55395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, point, &dof));
55405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(section, point, &off));
55419df71ca4SMatthew G. Knepley     varr = &vArray[off];
55421a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
55431a271a75SMatthew G. Knepley       array[offset] = varr[d];
55449df71ca4SMatthew G. Knepley     }
55459df71ca4SMatthew G. Knepley     size += dof;
55469df71ca4SMatthew G. Knepley   }
55479df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
55489df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
55499df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
55505a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
55515a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
55525a1bb5cfSMatthew G. Knepley 
555352ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, cp, &dof));
55555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(section, cp, &off));
55565a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55575a1bb5cfSMatthew G. Knepley     if (o >= 0) {
55581a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
55591a271a75SMatthew G. Knepley         array[offset] = varr[d];
55605a1bb5cfSMatthew G. Knepley       }
55615a1bb5cfSMatthew G. Knepley     } else {
55621a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
55631a271a75SMatthew G. Knepley         array[offset] = varr[d];
55645a1bb5cfSMatthew G. Knepley       }
55655a1bb5cfSMatthew G. Knepley     }
55669df71ca4SMatthew G. Knepley     size += dof;
55675a1bb5cfSMatthew G. Knepley   }
55685f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(v, &vArray));
55699df71ca4SMatthew G. Knepley   if (!*values) {
55705a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
55715a1bb5cfSMatthew G. Knepley     *values = array;
55729df71ca4SMatthew G. Knepley   } else {
55732c71b3e2SJacob Faibussowitsch     PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
55748c312ff3SMatthew G. Knepley     *csize = size;
55759df71ca4SMatthew G. Knepley   }
55765a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
55775a1bb5cfSMatthew G. Knepley }
5578d9917b9dSMatthew G. Knepley 
557927f02ce8SMatthew G. Knepley /* Compress out points not in the section */
55809fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
558127f02ce8SMatthew G. Knepley {
558227f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
558327f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
558427f02ce8SMatthew G. Knepley 
55855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd));
558627f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
558727f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
558827f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
558927f02ce8SMatthew G. Knepley       points[q*2]   = r;
559027f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
559127f02ce8SMatthew G. Knepley       ++q;
559227f02ce8SMatthew G. Knepley     }
559327f02ce8SMatthew G. Knepley   }
559427f02ce8SMatthew G. Knepley   *numPoints = q;
559527f02ce8SMatthew G. Knepley   return 0;
559627f02ce8SMatthew G. Knepley }
559727f02ce8SMatthew G. Knepley 
559897529cf3SJed Brown /* Compressed closure does not apply closure permutation */
55991dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5600923c78e0SToby Isaac {
560127f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5602923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5603923c78e0SToby Isaac 
5604923c78e0SToby Isaac   PetscFunctionBeginHot;
56055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints));
560627f02ce8SMatthew G. Knepley   if (*clPoints) {
5607923c78e0SToby Isaac     PetscInt dof, off;
5608923c78e0SToby Isaac 
56095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(*clSec, point, &dof));
56105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(*clSec, point, &off));
56115f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(*clPoints, &cla));
5612923c78e0SToby Isaac     np   = dof/2;
5613923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
561427f02ce8SMatthew G. Knepley   } else {
56155f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
56165f80ce2aSJacob Faibussowitsch     CHKERRQ(CompressPoints_Private(section, &np, pts));
5617923c78e0SToby Isaac   }
5618923c78e0SToby Isaac   *numPoints = np;
5619923c78e0SToby Isaac   *points    = pts;
5620923c78e0SToby Isaac   *clp       = cla;
5621923c78e0SToby Isaac   PetscFunctionReturn(0);
5622923c78e0SToby Isaac }
5623923c78e0SToby Isaac 
56241dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5625923c78e0SToby Isaac {
5626923c78e0SToby Isaac   PetscFunctionBeginHot;
5627923c78e0SToby Isaac   if (!*clPoints) {
56285f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5629923c78e0SToby Isaac   } else {
56305f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(*clPoints, clp));
5631923c78e0SToby Isaac   }
5632923c78e0SToby Isaac   *numPoints = 0;
5633923c78e0SToby Isaac   *points    = NULL;
5634923c78e0SToby Isaac   *clSec     = NULL;
5635923c78e0SToby Isaac   *clPoints  = NULL;
5636923c78e0SToby Isaac   *clp       = NULL;
5637923c78e0SToby Isaac   PetscFunctionReturn(0);
5638923c78e0SToby Isaac }
5639923c78e0SToby Isaac 
56409fbee547SJacob 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[])
56411a271a75SMatthew G. Knepley {
56421a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
564397e99dd9SToby Isaac   const PetscInt    **perms = NULL;
564497e99dd9SToby Isaac   const PetscScalar **flips = NULL;
56451a271a75SMatthew G. Knepley 
56461a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5647fe02ba77SJed Brown   *size = 0;
56485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
564997e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
565097e99dd9SToby Isaac     const PetscInt    point = points[2*p];
565197e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
565297e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
56531a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
56541a271a75SMatthew G. Knepley     const PetscScalar *varr;
56551a271a75SMatthew G. Knepley 
56565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, point, &dof));
56575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(section, point, &off));
56581a271a75SMatthew G. Knepley     varr = &vArray[off];
565997e99dd9SToby Isaac     if (clperm) {
566097e99dd9SToby Isaac       if (perm) {
566197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
56621a271a75SMatthew G. Knepley       } else {
566397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
566497e99dd9SToby Isaac       }
566597e99dd9SToby Isaac       if (flip) {
566697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
566797e99dd9SToby Isaac       }
566897e99dd9SToby Isaac     } else {
566997e99dd9SToby Isaac       if (perm) {
567097e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
567197e99dd9SToby Isaac       } else {
567297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
567397e99dd9SToby Isaac       }
567497e99dd9SToby Isaac       if (flip) {
567597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
56761a271a75SMatthew G. Knepley       }
56771a271a75SMatthew G. Knepley     }
567897e99dd9SToby Isaac     offset += dof;
567997e99dd9SToby Isaac   }
56805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
56811a271a75SMatthew G. Knepley   *size = offset;
56821a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
56831a271a75SMatthew G. Knepley }
56841a271a75SMatthew G. Knepley 
56859fbee547SJacob 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[])
56861a271a75SMatthew G. Knepley {
56871a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
56881a271a75SMatthew G. Knepley 
56891a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5690fe02ba77SJed Brown   *size = 0;
56911a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
569297e99dd9SToby Isaac     PetscInt          p;
569397e99dd9SToby Isaac     const PetscInt    **perms = NULL;
569497e99dd9SToby Isaac     const PetscScalar **flips = NULL;
56951a271a75SMatthew G. Knepley 
56965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
569797e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
569897e99dd9SToby Isaac       const PetscInt    point = points[2*p];
569997e99dd9SToby Isaac       PetscInt          fdof, foff, b;
57001a271a75SMatthew G. Knepley       const PetscScalar *varr;
570197e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
570297e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
57031a271a75SMatthew G. Knepley 
57045f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof));
57055f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldOffset(section, point, f, &foff));
57061a271a75SMatthew G. Knepley       varr = &vArray[foff];
570797e99dd9SToby Isaac       if (clperm) {
570897e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
570997e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
571097e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
57111a271a75SMatthew G. Knepley       } else {
571297e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
571397e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
571497e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
57151a271a75SMatthew G. Knepley       }
571697e99dd9SToby Isaac       offset += fdof;
57171a271a75SMatthew G. Knepley     }
57185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
57191a271a75SMatthew G. Knepley   }
57201a271a75SMatthew G. Knepley   *size = offset;
57211a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57221a271a75SMatthew G. Knepley }
57231a271a75SMatthew G. Knepley 
5724552f7358SJed Brown /*@C
5725552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5726552f7358SJed Brown 
5727552f7358SJed Brown   Not collective
5728552f7358SJed Brown 
5729552f7358SJed Brown   Input Parameters:
5730552f7358SJed Brown + dm - The DM
5731552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5732552f7358SJed Brown . v - The local vector
57336b867d5aSJose E. Roman - point - The point in the DM
5734552f7358SJed Brown 
57356b867d5aSJose E. Roman   Input/Output Parameters:
57366b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
57376b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
57386b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
573922c1ee49SMatthew G. Knepley 
574022c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
574122c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
574222c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
574322c1ee49SMatthew G. Knepley $
574422c1ee49SMatthew G. Knepley $ A typical use could be
574522c1ee49SMatthew G. Knepley $
574622c1ee49SMatthew G. Knepley $  values = NULL;
57475f80ce2aSJacob Faibussowitsch $  CHKERRQ(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
574822c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
574922c1ee49SMatthew G. Knepley $    <Compute on closure>
575022c1ee49SMatthew G. Knepley $  }
57515f80ce2aSJacob Faibussowitsch $  CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
575222c1ee49SMatthew G. Knepley $
575322c1ee49SMatthew G. Knepley $ or
575422c1ee49SMatthew G. Knepley $
575522c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
575622c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
575722c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
57585f80ce2aSJacob Faibussowitsch $    CHKERRQ(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
575922c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
576022c1ee49SMatthew G. Knepley $      <Compute on closure>
576122c1ee49SMatthew G. Knepley $    }
576222c1ee49SMatthew G. Knepley $  }
576322c1ee49SMatthew G. Knepley $  PetscFree(values);
5764552f7358SJed Brown 
5765552f7358SJed Brown   Fortran Notes:
5766552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5767552f7358SJed Brown   include petsc.h90 in your code.
5768552f7358SJed Brown 
5769552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5770552f7358SJed Brown 
5771552f7358SJed Brown   Level: intermediate
5772552f7358SJed Brown 
5773552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5774552f7358SJed Brown @*/
5775552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5776552f7358SJed Brown {
5777552f7358SJed Brown   PetscSection       clSection;
5778d9917b9dSMatthew G. Knepley   IS                 clPoints;
5779552f7358SJed Brown   PetscInt          *points = NULL;
5780c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5781c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5782552f7358SJed Brown 
5783d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5784552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57855f80ce2aSJacob Faibussowitsch   if (!section) CHKERRQ(DMGetLocalSection(dm, &section));
57861a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
57871a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
57885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
57895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
5790552f7358SJed Brown   if (depth == 1 && numFields < 2) {
57915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5792552f7358SJed Brown     PetscFunctionReturn(0);
5793552f7358SJed Brown   }
57941a271a75SMatthew G. Knepley   /* Get points */
57955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5796c459fbc1SJed Brown   /* Get sizes */
5797c459fbc1SJed Brown   asize = 0;
5798c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5799c459fbc1SJed Brown     PetscInt dof;
58005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, points[p], &dof));
58011a271a75SMatthew G. Knepley     asize += dof;
5802552f7358SJed Brown   }
5803c459fbc1SJed Brown   if (values) {
5804c459fbc1SJed Brown     const PetscScalar *vArray;
5805c459fbc1SJed Brown     PetscInt          size;
5806c459fbc1SJed Brown 
5807c459fbc1SJed Brown     if (*values) {
58082c71b3e2SJacob Faibussowitsch       PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize);
58095f80ce2aSJacob Faibussowitsch     } else CHKERRQ(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
58105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm));
58115f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(v, &vArray));
58121a271a75SMatthew G. Knepley     /* Get values */
58135f80ce2aSJacob Faibussowitsch     if (numFields > 0) CHKERRQ(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
58145f80ce2aSJacob Faibussowitsch     else               CHKERRQ(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
58152c71b3e2SJacob Faibussowitsch     PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size);
58161a271a75SMatthew G. Knepley     /* Cleanup array */
58175f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(v, &vArray));
5818d0f6b257SMatthew G. Knepley   }
5819c459fbc1SJed Brown   if (csize) *csize = asize;
5820c459fbc1SJed Brown   /* Cleanup points */
58215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5822552f7358SJed Brown   PetscFunctionReturn(0);
5823552f7358SJed Brown }
5824552f7358SJed Brown 
5825e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5826e5c487bfSMatthew G. Knepley {
5827e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5828e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5829e5c487bfSMatthew G. Knepley   IS                 clPoints;
5830e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5831e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5832e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5833c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5834c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5835e5c487bfSMatthew G. Knepley 
5836e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5837e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58385f80ce2aSJacob Faibussowitsch   if (!section) CHKERRQ(DMGetLocalSection(dm, &section));
5839e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5840e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &mdepth));
58425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthLabel(dm, &depthLabel));
58435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
5844e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
58455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5846e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5847e5c487bfSMatthew G. Knepley   }
5848e5c487bfSMatthew G. Knepley   /* Get points */
58495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5850c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5851c459fbc1SJed Brown     PetscInt dof;
58525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, points[2*p], &dof));
5853c459fbc1SJed Brown     clsize += dof;
5854c459fbc1SJed Brown   }
58555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm));
5856e5c487bfSMatthew G. Knepley   /* Filter points */
5857e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5858e5c487bfSMatthew G. Knepley     PetscInt dep;
5859e5c487bfSMatthew G. Knepley 
58605f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetValue(depthLabel, points[p], &dep));
5861e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5862e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5863e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5864e5c487bfSMatthew G. Knepley     ++Np;
5865e5c487bfSMatthew G. Knepley   }
5866e5c487bfSMatthew G. Knepley   /* Get array */
5867e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5868e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5869e5c487bfSMatthew G. Knepley 
5870e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
58715f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section, points[p], &dof));
5872e5c487bfSMatthew G. Knepley       asize += dof;
5873e5c487bfSMatthew G. Knepley     }
5874e5c487bfSMatthew G. Knepley     if (!values) {
58755f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5876e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5877e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5878e5c487bfSMatthew G. Knepley     }
58795f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
5880e5c487bfSMatthew G. Knepley   } else {
5881e5c487bfSMatthew G. Knepley     array = *values;
5882e5c487bfSMatthew G. Knepley   }
58835f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(v, &vArray));
5884e5c487bfSMatthew G. Knepley   /* Get values */
58855f80ce2aSJacob Faibussowitsch   if (numFields > 0) CHKERRQ(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
58865f80ce2aSJacob Faibussowitsch   else               CHKERRQ(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
5887e5c487bfSMatthew G. Knepley   /* Cleanup points */
58885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5889e5c487bfSMatthew G. Knepley   /* Cleanup array */
58905f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(v, &vArray));
5891e5c487bfSMatthew G. Knepley   if (!*values) {
5892e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5893e5c487bfSMatthew G. Knepley     *values = array;
5894e5c487bfSMatthew G. Knepley   } else {
58952c71b3e2SJacob Faibussowitsch     PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
5896e5c487bfSMatthew G. Knepley     *csize = size;
5897e5c487bfSMatthew G. Knepley   }
5898e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5899e5c487bfSMatthew G. Knepley }
5900e5c487bfSMatthew G. Knepley 
5901552f7358SJed Brown /*@C
5902552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5903552f7358SJed Brown 
5904552f7358SJed Brown   Not collective
5905552f7358SJed Brown 
5906552f7358SJed Brown   Input Parameters:
5907552f7358SJed Brown + dm - The DM
59080298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5909552f7358SJed Brown . v - The local vector
5910eaf898f9SPatrick Sanan . point - The point in the DM
59110298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5912552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5913552f7358SJed Brown 
591422c1ee49SMatthew 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()
591522c1ee49SMatthew G. Knepley 
59163813dfbdSMatthew G Knepley   Fortran Notes:
59173813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
59183813dfbdSMatthew G Knepley   include petsc.h90 in your code.
59193813dfbdSMatthew G Knepley 
59203813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
59213813dfbdSMatthew G Knepley 
5922552f7358SJed Brown   Level: intermediate
5923552f7358SJed Brown 
5924552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5925552f7358SJed Brown @*/
59267c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5927a6dfd86eSKarl Rupp {
5928552f7358SJed Brown   PetscInt       size = 0;
5929552f7358SJed Brown 
5930552f7358SJed Brown   PetscFunctionBegin;
5931552f7358SJed Brown   /* Should work without recalculating size */
59325f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values));
5933c9fdaa05SMatthew G. Knepley   *values = NULL;
5934552f7358SJed Brown   PetscFunctionReturn(0);
5935552f7358SJed Brown }
5936552f7358SJed Brown 
59379fbee547SJacob Faibussowitsch static inline void add   (PetscScalar *x, PetscScalar y) {*x += y;}
59389fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5939552f7358SJed Brown 
59409fbee547SJacob 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[])
5941552f7358SJed Brown {
5942552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5943552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5944552f7358SJed Brown   PetscScalar    *a;
5945552f7358SJed Brown   PetscInt        off, cind = 0, k;
5946552f7358SJed Brown 
5947552f7358SJed Brown   PetscFunctionBegin;
59485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetConstraintDof(section, point, &cdof));
59495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(section, point, &off));
5950552f7358SJed Brown   a    = &array[off];
5951552f7358SJed Brown   if (!cdof || setBC) {
595297e99dd9SToby Isaac     if (clperm) {
595397e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
595497e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5955552f7358SJed Brown     } else {
595697e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
595797e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5958552f7358SJed Brown     }
5959552f7358SJed Brown   } else {
59605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetConstraintIndices(section, point, &cdofs));
596197e99dd9SToby Isaac     if (clperm) {
596297e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
5963552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
596497e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
5965552f7358SJed Brown         }
5966552f7358SJed Brown       } else {
5967552f7358SJed Brown         for (k = 0; k < dof; ++k) {
5968552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
596997e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
597097e99dd9SToby Isaac         }
597197e99dd9SToby Isaac       }
597297e99dd9SToby Isaac     } else {
597397e99dd9SToby Isaac       if (perm) {
597497e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
597597e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
597697e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
597797e99dd9SToby Isaac         }
597897e99dd9SToby Isaac       } else {
597997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
598097e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
598197e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
598297e99dd9SToby Isaac         }
5983552f7358SJed Brown       }
5984552f7358SJed Brown     }
5985552f7358SJed Brown   }
5986552f7358SJed Brown   PetscFunctionReturn(0);
5987552f7358SJed Brown }
5988552f7358SJed Brown 
59899fbee547SJacob 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[])
5990a5e93ea8SMatthew G. Knepley {
5991a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
5992a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5993a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
5994a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
5995a5e93ea8SMatthew G. Knepley 
5996a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
59975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetConstraintDof(section, point, &cdof));
59985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetOffset(section, point, &off));
5999a5e93ea8SMatthew G. Knepley   a    = &array[off];
6000a5e93ea8SMatthew G. Knepley   if (cdof) {
60015f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetConstraintIndices(section, point, &cdofs));
600297e99dd9SToby Isaac     if (clperm) {
600397e99dd9SToby Isaac       if (perm) {
6004a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6005a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
600697e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
600797e99dd9SToby Isaac             cind++;
6008a5e93ea8SMatthew G. Knepley           }
6009a5e93ea8SMatthew G. Knepley         }
6010a5e93ea8SMatthew G. Knepley       } else {
6011a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6012a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
601397e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
601497e99dd9SToby Isaac             cind++;
601597e99dd9SToby Isaac           }
601697e99dd9SToby Isaac         }
601797e99dd9SToby Isaac       }
601897e99dd9SToby Isaac     } else {
601997e99dd9SToby Isaac       if (perm) {
602097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
602197e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
602297e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
602397e99dd9SToby Isaac             cind++;
602497e99dd9SToby Isaac           }
602597e99dd9SToby Isaac         }
602697e99dd9SToby Isaac       } else {
602797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
602897e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
602997e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
603097e99dd9SToby Isaac             cind++;
603197e99dd9SToby Isaac           }
6032a5e93ea8SMatthew G. Knepley         }
6033a5e93ea8SMatthew G. Knepley       }
6034a5e93ea8SMatthew G. Knepley     }
6035a5e93ea8SMatthew G. Knepley   }
6036a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6037a5e93ea8SMatthew G. Knepley }
6038a5e93ea8SMatthew G. Knepley 
60399fbee547SJacob 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[])
6040a6dfd86eSKarl Rupp {
6041552f7358SJed Brown   PetscScalar    *a;
60421a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60431a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
604497e99dd9SToby Isaac   PetscInt        cind = 0, b;
6045552f7358SJed Brown 
6046552f7358SJed Brown   PetscFunctionBegin;
60475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof));
60485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldOffset(section, point, f, &foff));
60501a271a75SMatthew G. Knepley   a    = &array[foff];
6051552f7358SJed Brown   if (!fcdof || setBC) {
605297e99dd9SToby Isaac     if (clperm) {
605397e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
605497e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
6055552f7358SJed Brown     } else {
605697e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
605797e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
6058552f7358SJed Brown     }
6059552f7358SJed Brown   } else {
60605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
606197e99dd9SToby Isaac     if (clperm) {
606297e99dd9SToby Isaac       if (perm) {
606397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
606497e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
606597e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6066552f7358SJed Brown         }
6067552f7358SJed Brown       } else {
606897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
606997e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
607097e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
607197e99dd9SToby Isaac         }
607297e99dd9SToby Isaac       }
607397e99dd9SToby Isaac     } else {
607497e99dd9SToby Isaac       if (perm) {
607597e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
607697e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
607797e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
607897e99dd9SToby Isaac         }
607997e99dd9SToby Isaac       } else {
608097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
608197e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
608297e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6083552f7358SJed Brown         }
6084552f7358SJed Brown       }
6085552f7358SJed Brown     }
6086552f7358SJed Brown   }
60871a271a75SMatthew G. Knepley   *offset += fdof;
6088552f7358SJed Brown   PetscFunctionReturn(0);
6089552f7358SJed Brown }
6090552f7358SJed Brown 
60919fbee547SJacob 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[])
6092a5e93ea8SMatthew G. Knepley {
6093a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
60941a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60951a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
60965da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6097ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6098a5e93ea8SMatthew G. Knepley 
6099a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
61005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldComponents(section, f, &Nc));
61015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof));
61025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
61035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetFieldOffset(section, point, f, &foff));
61041a271a75SMatthew G. Knepley   a    = &array[foff];
6105a5e93ea8SMatthew G. Knepley   if (fcdof) {
6106ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
61075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
610897e99dd9SToby Isaac     if (clperm) {
610997e99dd9SToby Isaac       if (perm) {
6110ba322698SMatthew G. Knepley         if (comps) {
6111ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6112ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61135da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6114ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6115ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
6116ba322698SMatthew G. Knepley           }
6117ba322698SMatthew G. Knepley         } else {
611897e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
611997e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
612097e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6121a5e93ea8SMatthew G. Knepley               ++cind;
6122a5e93ea8SMatthew G. Knepley             }
6123a5e93ea8SMatthew G. Knepley           }
6124ba322698SMatthew G. Knepley         }
6125ba322698SMatthew G. Knepley       } else {
6126ba322698SMatthew G. Knepley         if (comps) {
6127ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6128ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61295da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6130ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6131ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
6132ba322698SMatthew G. Knepley           }
6133a5e93ea8SMatthew G. Knepley         } else {
613497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
613597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
613697e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
613797e99dd9SToby Isaac               ++cind;
613897e99dd9SToby Isaac             }
613997e99dd9SToby Isaac           }
614097e99dd9SToby Isaac         }
6141ba322698SMatthew G. Knepley       }
614297e99dd9SToby Isaac     } else {
614397e99dd9SToby Isaac       if (perm) {
6144ba322698SMatthew G. Knepley         if (comps) {
6145ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6146ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61475da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6148ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6149ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
6150ba322698SMatthew G. Knepley           }
6151ba322698SMatthew G. Knepley         } else {
615297e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
615397e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
615497e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
615597e99dd9SToby Isaac               ++cind;
615697e99dd9SToby Isaac             }
615797e99dd9SToby Isaac           }
6158ba322698SMatthew G. Knepley         }
6159ba322698SMatthew G. Knepley       } else {
6160ba322698SMatthew G. Knepley         if (comps) {
6161ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6162ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61635da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6164ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6165ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
6166ba322698SMatthew G. Knepley           }
616797e99dd9SToby Isaac         } else {
616897e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
616997e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
617097e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6171a5e93ea8SMatthew G. Knepley               ++cind;
6172a5e93ea8SMatthew G. Knepley             }
6173a5e93ea8SMatthew G. Knepley           }
6174a5e93ea8SMatthew G. Knepley         }
6175a5e93ea8SMatthew G. Knepley       }
6176a5e93ea8SMatthew G. Knepley     }
6177ba322698SMatthew G. Knepley   }
61781a271a75SMatthew G. Knepley   *offset += fdof;
6179a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6180a5e93ea8SMatthew G. Knepley }
6181a5e93ea8SMatthew G. Knepley 
61829fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6183a6dfd86eSKarl Rupp {
6184552f7358SJed Brown   PetscScalar    *array;
61851b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
61861b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6187552f7358SJed Brown 
61881b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(section, &pStart, &pEnd));
61905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSize(dm, point, &numPoints));
61915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCone(dm, point, &cone));
61925f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeOrientation(dm, point, &coneO));
61935f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(v, &array));
6194b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6195b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
6196b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
6197b6ebb6e6SMatthew G. Knepley 
6198b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
61995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, cp, &dof));
6200b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6201b6ebb6e6SMatthew G. Knepley     {
6202b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6203b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6204b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6205b6ebb6e6SMatthew G. Knepley 
62065f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetConstraintDof(section, cp, &cdof));
62075f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(section, cp, &coff));
6208b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
6209b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6210b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6211b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6212b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6213b6ebb6e6SMatthew G. Knepley           }
6214b6ebb6e6SMatthew G. Knepley         } else {
6215b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6216b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6217b6ebb6e6SMatthew G. Knepley           }
6218b6ebb6e6SMatthew G. Knepley         }
6219b6ebb6e6SMatthew G. Knepley       } else {
62205f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6221b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6222b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6223b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6224b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6225b6ebb6e6SMatthew G. Knepley           }
6226b6ebb6e6SMatthew G. Knepley         } else {
6227b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6228b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6229b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6230b6ebb6e6SMatthew G. Knepley           }
6231b6ebb6e6SMatthew G. Knepley         }
6232b6ebb6e6SMatthew G. Knepley       }
6233b6ebb6e6SMatthew G. Knepley     }
6234b6ebb6e6SMatthew G. Knepley   }
62355f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(v, &array));
6236b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6237b6ebb6e6SMatthew G. Knepley }
62381b406b76SMatthew G. Knepley 
62391b406b76SMatthew G. Knepley /*@C
62401b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62411b406b76SMatthew G. Knepley 
62421b406b76SMatthew G. Knepley   Not collective
62431b406b76SMatthew G. Knepley 
62441b406b76SMatthew G. Knepley   Input Parameters:
62451b406b76SMatthew G. Knepley + dm - The DM
62461b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62471b406b76SMatthew G. Knepley . v - The local vector
6248eaf898f9SPatrick Sanan . point - The point in the DM
62491b406b76SMatthew G. Knepley . values - The array of values
625022c1ee49SMatthew 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,
625122c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62521b406b76SMatthew G. Knepley 
62531b406b76SMatthew G. Knepley   Fortran Notes:
62541b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62551b406b76SMatthew G. Knepley 
62561b406b76SMatthew G. Knepley   Level: intermediate
62571b406b76SMatthew G. Knepley 
62581b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure()
62591b406b76SMatthew G. Knepley @*/
62601b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
62611b406b76SMatthew G. Knepley {
62621b406b76SMatthew G. Knepley   PetscSection    clSection;
62631b406b76SMatthew G. Knepley   IS              clPoints;
62641b406b76SMatthew G. Knepley   PetscScalar    *array;
62651b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
626627f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6267c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
62681b406b76SMatthew G. Knepley 
62691a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
62701b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62715f80ce2aSJacob Faibussowitsch   if (!section) CHKERRQ(DMGetLocalSection(dm, &section));
62721a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
62731a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
62745f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
62755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
62761b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
62775f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
62781b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
62791b406b76SMatthew G. Knepley   }
62801a271a75SMatthew G. Knepley   /* Get points */
62815f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6282c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6283c459fbc1SJed Brown     PetscInt dof;
62845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, points[2*p], &dof));
6285c459fbc1SJed Brown     clsize += dof;
6286c459fbc1SJed Brown   }
62875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
62881a271a75SMatthew G. Knepley   /* Get array */
62895f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(v, &array));
62901a271a75SMatthew G. Knepley   /* Get values */
6291ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
629297e99dd9SToby Isaac     PetscInt offset = 0, f;
6293552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
629497e99dd9SToby Isaac       const PetscInt    **perms = NULL;
629597e99dd9SToby Isaac       const PetscScalar **flips = NULL;
629697e99dd9SToby Isaac 
62975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6298552f7358SJed Brown       switch (mode) {
6299552f7358SJed Brown       case INSERT_VALUES:
630097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
630197e99dd9SToby Isaac           const PetscInt    point = points[2*p];
630297e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
630397e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
630497e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6305552f7358SJed Brown         } break;
6306552f7358SJed Brown       case INSERT_ALL_VALUES:
630797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
630897e99dd9SToby Isaac           const PetscInt    point = points[2*p];
630997e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
631097e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
631197e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6312552f7358SJed Brown         } break;
6313a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
631497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
631597e99dd9SToby Isaac           const PetscInt    point = points[2*p];
631697e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
631797e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6318ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6319a5e93ea8SMatthew G. Knepley         } break;
6320552f7358SJed Brown       case ADD_VALUES:
632197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632297e99dd9SToby Isaac           const PetscInt    point = points[2*p];
632397e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
632497e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
632597e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6326552f7358SJed Brown         } break;
6327552f7358SJed Brown       case ADD_ALL_VALUES:
632897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632997e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633097e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633197e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
633297e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6333552f7358SJed Brown         } break;
6334304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
633597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633697e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633797e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633897e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6339ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6340304ab55fSMatthew G. Knepley         } break;
6341552f7358SJed Brown       default:
634298921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6343552f7358SJed Brown       }
63445f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
63451a271a75SMatthew G. Knepley     }
6346552f7358SJed Brown   } else {
63471a271a75SMatthew G. Knepley     PetscInt dof, off;
634897e99dd9SToby Isaac     const PetscInt    **perms = NULL;
634997e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63501a271a75SMatthew G. Knepley 
63515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
6352552f7358SJed Brown     switch (mode) {
6353552f7358SJed Brown     case INSERT_VALUES:
635497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
635597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
635697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
635797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63585f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section, point, &dof));
635997e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
6360552f7358SJed Brown       } break;
6361552f7358SJed Brown     case INSERT_ALL_VALUES:
636297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
636397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
636497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
636597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63665f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section, point, &dof));
636797e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6368552f7358SJed Brown       } break;
6369a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
637097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
637197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
637297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
637397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63745f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section, point, &dof));
637597e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6376a5e93ea8SMatthew G. Knepley       } break;
6377552f7358SJed Brown     case ADD_VALUES:
637897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
637997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63825f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section, point, &dof));
638397e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6384552f7358SJed Brown       } break;
6385552f7358SJed Brown     case ADD_ALL_VALUES:
638697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63905f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section, point, &dof));
639197e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6392552f7358SJed Brown       } break;
6393304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
639497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
639597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
639697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63985f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section, point, &dof));
639997e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6400304ab55fSMatthew G. Knepley       } break;
6401552f7358SJed Brown     default:
640298921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6403552f7358SJed Brown     }
64045f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
6405552f7358SJed Brown   }
64061a271a75SMatthew G. Knepley   /* Cleanup points */
64075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
64081a271a75SMatthew G. Knepley   /* Cleanup array */
64095f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(v, &array));
6410552f7358SJed Brown   PetscFunctionReturn(0);
6411552f7358SJed Brown }
6412552f7358SJed Brown 
64135f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
64149fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
64155f790a90SMatthew G. Knepley {
64165f790a90SMatthew G. Knepley   PetscFunctionBegin;
64175f790a90SMatthew G. Knepley   if (label) {
64185f790a90SMatthew G. Knepley     PetscInt       val, fdof;
64195f790a90SMatthew G. Knepley 
64205f790a90SMatthew G. Knepley     /* There is a problem with this:
64215f790a90SMatthew 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
64225f790a90SMatthew 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.
64235f790a90SMatthew G. Knepley        Thus I am only going to check val != -1, not val != labelId
64245f790a90SMatthew G. Knepley     */
64255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetValue(label, point, &val));
64265f790a90SMatthew G. Knepley     if (val < 0) {
64275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof));
64285f790a90SMatthew G. Knepley       *offset += fdof;
64295f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
64305f790a90SMatthew G. Knepley     }
64315f790a90SMatthew G. Knepley   }
64325f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64335f790a90SMatthew G. Knepley }
64345f790a90SMatthew G. Knepley 
643597529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64365f790a90SMatthew 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)
6437e07394fbSMatthew G. Knepley {
6438e07394fbSMatthew G. Knepley   PetscSection    clSection;
6439e07394fbSMatthew G. Knepley   IS              clPoints;
6440e07394fbSMatthew G. Knepley   PetscScalar    *array;
6441e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
644297529cf3SJed Brown   const PetscInt *clp;
6443e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
644497e99dd9SToby Isaac   PetscInt        offset = 0, f;
6445e07394fbSMatthew G. Knepley 
6446e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6447e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64485f80ce2aSJacob Faibussowitsch   if (!section) CHKERRQ(DMGetLocalSection(dm, &section));
6449e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6450e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
6452e07394fbSMatthew G. Knepley   /* Get points */
64535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6454e07394fbSMatthew G. Knepley   /* Get array */
64555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(v, &array));
6456e07394fbSMatthew G. Knepley   /* Get values */
6457e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
645897e99dd9SToby Isaac     const PetscInt    **perms = NULL;
645997e99dd9SToby Isaac     const PetscScalar **flips = NULL;
646097e99dd9SToby Isaac 
6461e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6462e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6463e07394fbSMatthew G. Knepley         PetscInt fdof;
64645f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6465e07394fbSMatthew G. Knepley         offset += fdof;
6466e07394fbSMatthew G. Knepley       }
6467e07394fbSMatthew G. Knepley       continue;
6468e07394fbSMatthew G. Knepley     }
64695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6470e07394fbSMatthew G. Knepley     switch (mode) {
6471e07394fbSMatthew G. Knepley     case INSERT_VALUES:
647297e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
647397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
647497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
647597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64765f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64775f80ce2aSJacob Faibussowitsch         CHKERRQ(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
6478e07394fbSMatthew G. Knepley       } break;
6479e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
648097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
648197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
648297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
648397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64845f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64855f80ce2aSJacob Faibussowitsch         CHKERRQ(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
6486e07394fbSMatthew G. Knepley       } break;
6487e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
648897e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
648997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
649097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64925f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64935f80ce2aSJacob Faibussowitsch         CHKERRQ(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
6494e07394fbSMatthew G. Knepley       } break;
6495e07394fbSMatthew G. Knepley     case ADD_VALUES:
649697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
649897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65005f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65015f80ce2aSJacob Faibussowitsch         CHKERRQ(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
6502e07394fbSMatthew G. Knepley       } break;
6503e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
650497e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
650797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65085f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65095f80ce2aSJacob Faibussowitsch         CHKERRQ(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
6510e07394fbSMatthew G. Knepley       } break;
6511e07394fbSMatthew G. Knepley     default:
651298921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6513e07394fbSMatthew G. Knepley     }
65145f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6515e07394fbSMatthew G. Knepley   }
6516e07394fbSMatthew G. Knepley   /* Cleanup points */
65175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6518e07394fbSMatthew G. Knepley   /* Cleanup array */
65195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(v, &array));
6520e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6521e07394fbSMatthew G. Knepley }
6522e07394fbSMatthew G. Knepley 
65237cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6524552f7358SJed Brown {
6525552f7358SJed Brown   PetscMPIInt    rank;
6526552f7358SJed Brown   PetscInt       i, j;
6527552f7358SJed Brown 
6528552f7358SJed Brown   PetscFunctionBegin;
65295f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
65305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point));
65315f80ce2aSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]));
65325f80ce2aSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]));
6533b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6534557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6535b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
65365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6537b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6538519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65395f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j])));
6540552f7358SJed Brown #else
65415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]));
6542552f7358SJed Brown #endif
6543552f7358SJed Brown     }
65445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer, "\n"));
6545552f7358SJed Brown   }
6546552f7358SJed Brown   PetscFunctionReturn(0);
6547552f7358SJed Brown }
6548552f7358SJed Brown 
654905586334SMatthew G. Knepley /*
655005586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
655105586334SMatthew G. Knepley 
655205586334SMatthew G. Knepley   Input Parameters:
655305586334SMatthew G. Knepley + section - The section for this data layout
655436fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
655505586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
655605586334SMatthew G. Knepley . off     - The global offset of this point
655705586334SMatthew G. Knepley . loff    - The local offset of each field
6558a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
655905586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
656005586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
656105586334SMatthew G. Knepley 
656205586334SMatthew G. Knepley   Output Parameter:
656305586334SMatthew G. Knepley . indices - Indices for dofs on this point
656405586334SMatthew G. Knepley 
656505586334SMatthew G. Knepley   Level: developer
656605586334SMatthew G. Knepley 
656705586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
656805586334SMatthew G. Knepley */
656936fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6570a6dfd86eSKarl Rupp {
6571e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6572552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6573552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6574552f7358SJed Brown   PetscInt        cind = 0, k;
6575552f7358SJed Brown 
6576552f7358SJed Brown   PetscFunctionBegin;
65772c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
65785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetDof(section, point, &dof));
65795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetConstraintDof(section, point, &cdof));
6580552f7358SJed Brown   if (!cdof || setBC) {
658105586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
658205586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
658305586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
658405586334SMatthew G. Knepley 
658505586334SMatthew G. Knepley       indices[ind] = off + k;
6586552f7358SJed Brown     }
6587552f7358SJed Brown   } else {
65885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetConstraintIndices(section, point, &cdofs));
65894acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
659005586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
659105586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
659205586334SMatthew G. Knepley 
65934acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
65944acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
659505586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
65964acb8e1eSToby Isaac         ++cind;
65974acb8e1eSToby Isaac       } else {
659836fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6599552f7358SJed Brown       }
6600552f7358SJed Brown     }
6601552f7358SJed Brown   }
6602e6ccafaeSMatthew G Knepley   *loff += dof;
6603552f7358SJed Brown   PetscFunctionReturn(0);
6604552f7358SJed Brown }
6605552f7358SJed Brown 
66067e29afd2SMatthew G. Knepley /*
660736fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
66087e29afd2SMatthew G. Knepley 
660936fa2b79SJed Brown  Input Parameters:
661036fa2b79SJed Brown + section - a section (global or local)
661136fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
661236fa2b79SJed Brown . point - point within section
661336fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
661436fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
661536fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
661636fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
661736fa2b79SJed Brown . permsoff - offset
661836fa2b79SJed Brown - indperm - index permutation
661936fa2b79SJed Brown 
662036fa2b79SJed Brown  Output Parameter:
662136fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
662236fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
662336fa2b79SJed Brown 
662436fa2b79SJed Brown  Notes:
662536fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
662636fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
662736fa2b79SJed Brown  in the local vector.
662836fa2b79SJed Brown 
662936fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
663036fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
663136fa2b79SJed Brown 
663236fa2b79SJed Brown  Developer Note:
663336fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
663436fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
663536fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
663636fa2b79SJed Brown 
663736fa2b79SJed Brown  Example:
663836fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
663936fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
664036fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
664136fa2b79SJed 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.
664236fa2b79SJed Brown 
664336fa2b79SJed Brown  Level: developer
66447e29afd2SMatthew G. Knepley */
664536fa2b79SJed 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[])
6646a6dfd86eSKarl Rupp {
6647552f7358SJed Brown   PetscInt       numFields, foff, f;
6648552f7358SJed Brown 
6649552f7358SJed Brown   PetscFunctionBegin;
66502c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
66515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
6652552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66534acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6654552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66554acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66564acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6657552f7358SJed Brown 
66585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof));
66595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
6660552f7358SJed Brown     if (!cfdof || setBC) {
666105586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
666205586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
666305586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
666405586334SMatthew G. Knepley 
666505586334SMatthew G. Knepley         indices[ind] = off+foff+b;
666605586334SMatthew G. Knepley       }
6667552f7358SJed Brown     } else {
66685f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
666905586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
667005586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
667105586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
667205586334SMatthew G. Knepley 
66734acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
667405586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6675552f7358SJed Brown           ++cind;
6676552f7358SJed Brown         } else {
667736fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6678552f7358SJed Brown         }
6679552f7358SJed Brown       }
6680552f7358SJed Brown     }
668136fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6682552f7358SJed Brown     foffs[f] += fdof;
6683552f7358SJed Brown   }
6684552f7358SJed Brown   PetscFunctionReturn(0);
6685552f7358SJed Brown }
6686552f7358SJed Brown 
66877e29afd2SMatthew G. Knepley /*
66887e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
66897e29afd2SMatthew G. Knepley 
66907e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6691645102dcSJed Brown 
6692645102dcSJed Brown  Notes:
6693645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6694645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
66957e29afd2SMatthew G. Knepley */
6696645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
66977e29afd2SMatthew G. Knepley {
66987e29afd2SMatthew G. Knepley   PetscInt       numFields, foff, f;
66997e29afd2SMatthew G. Knepley 
67007e29afd2SMatthew G. Knepley   PetscFunctionBegin;
67015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
67027e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
67037e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
67047e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67057e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
67067e29afd2SMatthew G. Knepley     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
67077e29afd2SMatthew G. Knepley 
67085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldDof(section, point, f, &fdof));
67095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
67105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
6711645102dcSJed Brown     if (!cfdof) {
671205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
671305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
671405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
671505586334SMatthew G. Knepley 
671605586334SMatthew G. Knepley         indices[ind] = foff+b;
671705586334SMatthew G. Knepley       }
67187e29afd2SMatthew G. Knepley     } else {
67195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
672005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
672105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
672205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
672305586334SMatthew G. Knepley 
67247e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
672505586334SMatthew G. Knepley           indices[ind] = -(foff+b+1);
67267e29afd2SMatthew G. Knepley           ++cind;
67277e29afd2SMatthew G. Knepley         } else {
672805586334SMatthew G. Knepley           indices[ind] = foff+b-cind;
67297e29afd2SMatthew G. Knepley         }
67307e29afd2SMatthew G. Knepley       }
67317e29afd2SMatthew G. Knepley     }
67327e29afd2SMatthew G. Knepley     foffs[f] += fdof;
67337e29afd2SMatthew G. Knepley   }
67347e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
67357e29afd2SMatthew G. Knepley }
67367e29afd2SMatthew G. Knepley 
67374acb8e1eSToby 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)
6738d3d1a6afSToby Isaac {
6739d3d1a6afSToby Isaac   Mat             cMat;
6740d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6741d3d1a6afSToby Isaac   IS              aIS;
6742d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6743d3d1a6afSToby Isaac   const PetscInt  *anchors;
6744e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6745d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6746d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6747d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6748d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6749d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6750d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6751d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
67526ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6753d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6754d3d1a6afSToby Isaac 
6755d3d1a6afSToby Isaac   PetscFunctionBegin;
6756d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6757d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
67585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &numFields));
6759d3d1a6afSToby Isaac 
67605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS));
6761d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6762d3d1a6afSToby Isaac   if (aSec) {
67635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(newOffsets, 32));
67645f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(aIS,&anchors));
67655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(aSec,&aStart,&aEnd));
6766d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6767d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6768d3d1a6afSToby Isaac      * into the global matrix anyway) */
6769d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6770d3d1a6afSToby Isaac       PetscInt b    = points[p];
67714b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6772d3d1a6afSToby Isaac 
67735f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section,b,&bSecDof));
67744b2f2278SToby Isaac       if (!bSecDof) {
67754b2f2278SToby Isaac         continue;
67764b2f2278SToby Isaac       }
6777d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
67785f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec,b,&bDof));
6779d3d1a6afSToby Isaac       }
6780d3d1a6afSToby Isaac       if (bDof) {
6781d3d1a6afSToby Isaac         /* this point is constrained */
6782d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6783d3d1a6afSToby Isaac         PetscInt bOff, q;
6784d3d1a6afSToby Isaac 
6785d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6786d3d1a6afSToby Isaac         newNumPoints  += bDof;
67875f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(aSec,b,&bOff));
6788d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6789d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6790d3d1a6afSToby Isaac           PetscInt aDof;
6791d3d1a6afSToby Isaac 
67925f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetDof(section,a,&aDof));
6793d3d1a6afSToby Isaac           newNumIndices += aDof;
6794d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6795d3d1a6afSToby Isaac             PetscInt fDof;
6796d3d1a6afSToby Isaac 
67975f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldDof(section, a, f, &fDof));
6798d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6799d3d1a6afSToby Isaac           }
6800d3d1a6afSToby Isaac         }
6801d3d1a6afSToby Isaac       }
6802d3d1a6afSToby Isaac       else {
6803d3d1a6afSToby Isaac         /* this point is not constrained */
6804d3d1a6afSToby Isaac         newNumPoints++;
68054b2f2278SToby Isaac         newNumIndices += bSecDof;
6806d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6807d3d1a6afSToby Isaac           PetscInt fDof;
6808d3d1a6afSToby Isaac 
68095f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(section, b, f, &fDof));
6810d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6811d3d1a6afSToby Isaac         }
6812d3d1a6afSToby Isaac       }
6813d3d1a6afSToby Isaac     }
6814d3d1a6afSToby Isaac   }
6815d3d1a6afSToby Isaac   if (!anyConstrained) {
681672b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
681772b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
681872b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
681972b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
68205f80ce2aSJacob Faibussowitsch     if (aSec) CHKERRQ(ISRestoreIndices(aIS,&anchors));
6821d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6822d3d1a6afSToby Isaac   }
6823d3d1a6afSToby Isaac 
68246ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
68256ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68266ecaa68aSToby Isaac 
6827f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6828d3d1a6afSToby Isaac 
68296ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68306ecaa68aSToby Isaac     if (offsets) {
68316ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
68326ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
68336ecaa68aSToby Isaac       }
68346ecaa68aSToby Isaac     }
68355f80ce2aSJacob Faibussowitsch     if (aSec) CHKERRQ(ISRestoreIndices(aIS,&anchors));
68366ecaa68aSToby Isaac     PetscFunctionReturn(0);
68376ecaa68aSToby Isaac   }
68386ecaa68aSToby Isaac 
68392c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices);
6840d3d1a6afSToby Isaac 
68415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
6842d3d1a6afSToby Isaac 
6843d3d1a6afSToby Isaac   /* workspaces */
6844d3d1a6afSToby Isaac   if (numFields) {
6845d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
68465f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
68475f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
6848d3d1a6afSToby Isaac     }
6849d3d1a6afSToby Isaac   }
6850d3d1a6afSToby Isaac   else {
68515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
68525f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]));
6853d3d1a6afSToby Isaac   }
6854d3d1a6afSToby Isaac 
6855d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6856d3d1a6afSToby Isaac   if (numFields) {
68574b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68584b2f2278SToby Isaac 
6859d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6860d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
68614b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6862d3d1a6afSToby Isaac 
68635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section,b,&bSecDof));
68644b2f2278SToby Isaac       if (!bSecDof) {
68654b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
68664b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
68674b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
68684b2f2278SToby Isaac         }
68694b2f2278SToby Isaac         continue;
68704b2f2278SToby Isaac       }
6871d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
68725f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec, b, &bDof));
6873d3d1a6afSToby Isaac       }
6874d3d1a6afSToby Isaac       if (bDof) {
6875d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6876d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6877d3d1a6afSToby Isaac 
68785f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(section, b, f, &fDof));
68795f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetOffset(aSec, b, &bOff));
6880d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6881d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6882d3d1a6afSToby Isaac             PetscInt aFDof;
6883d3d1a6afSToby Isaac 
68845f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldDof(section, a, f, &aFDof));
6885d3d1a6afSToby Isaac             allFDof += aFDof;
6886d3d1a6afSToby Isaac           }
6887d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6888d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6889d3d1a6afSToby Isaac         }
6890d3d1a6afSToby Isaac       }
6891d3d1a6afSToby Isaac       else {
6892d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6893d3d1a6afSToby Isaac           PetscInt fDof;
6894d3d1a6afSToby Isaac 
68955f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(section, b, f, &fDof));
6896d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6897d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6898d3d1a6afSToby Isaac         }
6899d3d1a6afSToby Isaac       }
6900d3d1a6afSToby Isaac     }
69014b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
69024b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
69034b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6904d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6905d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6906d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6907d3d1a6afSToby Isaac       }
690819f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
690919f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
69105f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
6911d3d1a6afSToby Isaac     }
6912d3d1a6afSToby Isaac   }
6913d3d1a6afSToby Isaac   else {
6914d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6915d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
69164b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6917d3d1a6afSToby Isaac 
69185f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section,b,&bSecDof));
69194b2f2278SToby Isaac       if (!bSecDof) {
69204b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69214b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69224b2f2278SToby Isaac         continue;
69234b2f2278SToby Isaac       }
6924d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69255f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec, b, &bDof));
6926d3d1a6afSToby Isaac       }
6927d3d1a6afSToby Isaac       if (bDof) {
69284b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6929d3d1a6afSToby Isaac 
69305f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(aSec, b, &bOff));
6931d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6932d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6933d3d1a6afSToby Isaac 
69345f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetDof(section, a, &aDof));
6935d3d1a6afSToby Isaac           allDof += aDof;
6936d3d1a6afSToby Isaac         }
6937d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
69384b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6939d3d1a6afSToby Isaac       }
6940d3d1a6afSToby Isaac       else {
69414b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6942d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6943d3d1a6afSToby Isaac       }
6944d3d1a6afSToby Isaac     }
6945d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6946d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6947d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6948d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6949d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6950d3d1a6afSToby Isaac     }
69515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
6952d3d1a6afSToby Isaac   }
6953d3d1a6afSToby Isaac 
69546ecaa68aSToby Isaac   /* output arrays */
69555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
69566ecaa68aSToby Isaac 
6957d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
69585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetMaxDof(aSec, &maxAnchor));
69595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetMaxDof(section, &maxDof));
69605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices));
69615f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
6962d3d1a6afSToby Isaac   if (numFields) {
6963d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6964d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6965d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
69664b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6967d3d1a6afSToby Isaac 
69685f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section, b, &bSecDof));
69694b2f2278SToby Isaac       if (!bSecDof) {
69704b2f2278SToby Isaac         continue;
69714b2f2278SToby Isaac       }
6972d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69735f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec, b, &bDof));
6974d3d1a6afSToby Isaac       }
6975d3d1a6afSToby Isaac       if (bDof) {
6976d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6977d3d1a6afSToby Isaac 
6978d3d1a6afSToby Isaac         fStart[0] = 0;
6979d3d1a6afSToby Isaac         fEnd[0]   = 0;
6980d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6981d3d1a6afSToby Isaac           PetscInt fDof;
6982d3d1a6afSToby Isaac 
69835f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(cSec, b, f, &fDof));
6984d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
6985d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
6986d3d1a6afSToby Isaac         }
69875f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(cSec, b, &bOff));
69885f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
6989d3d1a6afSToby Isaac 
6990d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
6991d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
6992d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6993d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
6994d3d1a6afSToby Isaac 
6995d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
6996d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
6997d3d1a6afSToby Isaac         }
69985f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(aSec, b, &bOff));
6999d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7000d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7001d3d1a6afSToby Isaac 
7002d3d1a6afSToby 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 */
7003d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7004d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70055f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetOffset(section, a, &aOff));
70065f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7007d3d1a6afSToby Isaac         }
7008d3d1a6afSToby Isaac         newP += bDof;
7009d3d1a6afSToby Isaac 
70106ecaa68aSToby Isaac         if (outValues) {
7011d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
7012d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
70135f80ce2aSJacob Faibussowitsch             CHKERRQ(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]));
7014d3d1a6afSToby Isaac           }
7015d3d1a6afSToby Isaac         }
70166ecaa68aSToby Isaac       }
7017d3d1a6afSToby Isaac       else {
7018d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7019d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7020d3d1a6afSToby Isaac         newP++;
7021d3d1a6afSToby Isaac       }
7022d3d1a6afSToby Isaac     }
7023d3d1a6afSToby Isaac   } else {
7024d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7025d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
7026d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70274b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7028d3d1a6afSToby Isaac 
70295f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section, b, &bSecDof));
70304b2f2278SToby Isaac       if (!bSecDof) {
70314b2f2278SToby Isaac         continue;
70324b2f2278SToby Isaac       }
7033d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
70345f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec, b, &bDof));
7035d3d1a6afSToby Isaac       }
7036d3d1a6afSToby Isaac       if (bDof) {
7037d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7038d3d1a6afSToby Isaac 
70395f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(cSec, b, &bOff));
70405f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7041d3d1a6afSToby Isaac 
70425f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset (aSec, b, &bOff));
7043d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7044d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7045d3d1a6afSToby Isaac 
7046d3d1a6afSToby 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 */
7047d3d1a6afSToby Isaac 
7048d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7049d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70505f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetOffset(section, a, &aOff));
70515f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7052d3d1a6afSToby Isaac         }
7053d3d1a6afSToby Isaac         newP += bDof;
7054d3d1a6afSToby Isaac 
7055d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
70566ecaa68aSToby Isaac         if (outValues) {
70575f80ce2aSJacob Faibussowitsch           CHKERRQ(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]));
7058d3d1a6afSToby Isaac         }
70596ecaa68aSToby Isaac       }
7060d3d1a6afSToby Isaac       else {
7061d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7062d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7063d3d1a6afSToby Isaac         newP++;
7064d3d1a6afSToby Isaac       }
7065d3d1a6afSToby Isaac     }
7066d3d1a6afSToby Isaac   }
7067d3d1a6afSToby Isaac 
70686ecaa68aSToby Isaac   if (outValues) {
70695f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
70705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(tmpValues,newNumIndices*numIndices));
7071d3d1a6afSToby Isaac     /* multiply constraints on the right */
7072d3d1a6afSToby Isaac     if (numFields) {
7073d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7074d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7075d3d1a6afSToby Isaac 
7076d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7077d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7078d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7079d3d1a6afSToby Isaac           PetscInt c, r, k;
7080d3d1a6afSToby Isaac           PetscInt dof;
7081d3d1a6afSToby Isaac 
70825f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(section,b,f,&dof));
70834b2f2278SToby Isaac           if (!dof) {
70844b2f2278SToby Isaac             continue;
70854b2f2278SToby Isaac           }
7086d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7087d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
7088d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
7089d3d1a6afSToby Isaac 
7090d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7091d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7092d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
70934acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7094d3d1a6afSToby Isaac                 }
7095d3d1a6afSToby Isaac               }
7096d3d1a6afSToby Isaac             }
7097d3d1a6afSToby Isaac           }
7098d3d1a6afSToby Isaac           else {
7099d3d1a6afSToby Isaac             /* copy this column as is */
7100d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7101d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
7102d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7103d3d1a6afSToby Isaac               }
7104d3d1a6afSToby Isaac             }
7105d3d1a6afSToby Isaac           }
7106d3d1a6afSToby Isaac           oldOff += dof;
7107d3d1a6afSToby Isaac         }
7108d3d1a6afSToby Isaac       }
7109d3d1a6afSToby Isaac     }
7110d3d1a6afSToby Isaac     else {
7111d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7112d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7113d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7114d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7115d3d1a6afSToby Isaac         PetscInt c, r, k;
7116d3d1a6afSToby Isaac         PetscInt dof;
7117d3d1a6afSToby Isaac 
71185f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section,b,&dof));
71194b2f2278SToby Isaac         if (!dof) {
71204b2f2278SToby Isaac           continue;
71214b2f2278SToby Isaac         }
7122d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7123d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
7124d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
7125d3d1a6afSToby Isaac 
7126d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7127d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7128d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
7129d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7130d3d1a6afSToby Isaac               }
7131d3d1a6afSToby Isaac             }
7132d3d1a6afSToby Isaac           }
7133d3d1a6afSToby Isaac         }
7134d3d1a6afSToby Isaac         else {
7135d3d1a6afSToby Isaac           /* copy this column as is */
7136d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7137d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
7138d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7139d3d1a6afSToby Isaac             }
7140d3d1a6afSToby Isaac           }
7141d3d1a6afSToby Isaac         }
7142d3d1a6afSToby Isaac         oldOff += dof;
7143d3d1a6afSToby Isaac       }
7144d3d1a6afSToby Isaac     }
7145d3d1a6afSToby Isaac 
71466ecaa68aSToby Isaac     if (multiplyLeft) {
71475f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues));
71485f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(newValues,newNumIndices*newNumIndices));
7149d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7150d3d1a6afSToby Isaac       if (numFields) {
7151d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7152d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7153d3d1a6afSToby Isaac 
7154d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7155d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7156d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7157d3d1a6afSToby Isaac             PetscInt c, r, k;
7158d3d1a6afSToby Isaac             PetscInt dof;
7159d3d1a6afSToby Isaac 
71605f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldDof(section,b,f,&dof));
7161d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7162d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
7163d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
7164d3d1a6afSToby Isaac 
7165d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7166d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7167d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
7168d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7169d3d1a6afSToby Isaac                   }
7170d3d1a6afSToby Isaac                 }
7171d3d1a6afSToby Isaac               }
7172d3d1a6afSToby Isaac             }
7173d3d1a6afSToby Isaac             else {
7174d3d1a6afSToby Isaac               /* copy this row as is */
7175d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7176d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7177d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7178d3d1a6afSToby Isaac                 }
7179d3d1a6afSToby Isaac               }
7180d3d1a6afSToby Isaac             }
7181d3d1a6afSToby Isaac             oldOff += dof;
7182d3d1a6afSToby Isaac           }
7183d3d1a6afSToby Isaac         }
7184d3d1a6afSToby Isaac       }
7185d3d1a6afSToby Isaac       else {
7186d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7187d3d1a6afSToby Isaac 
7188d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7189d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7190d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7191d3d1a6afSToby Isaac           PetscInt c, r, k;
7192d3d1a6afSToby Isaac           PetscInt dof;
7193d3d1a6afSToby Isaac 
71945f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetDof(section,b,&dof));
7195d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7196d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
7197d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
7198d3d1a6afSToby Isaac 
7199d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7200d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7201d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
7202d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7203d3d1a6afSToby Isaac                 }
7204d3d1a6afSToby Isaac               }
7205d3d1a6afSToby Isaac             }
7206d3d1a6afSToby Isaac           }
7207d3d1a6afSToby Isaac           else {
7208d3d1a6afSToby Isaac             /* copy this row as is */
72099fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7210d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7211d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7212d3d1a6afSToby Isaac               }
7213d3d1a6afSToby Isaac             }
7214d3d1a6afSToby Isaac           }
7215d3d1a6afSToby Isaac           oldOff += dof;
7216d3d1a6afSToby Isaac         }
7217d3d1a6afSToby Isaac       }
7218d3d1a6afSToby Isaac 
72195f80ce2aSJacob Faibussowitsch       CHKERRQ(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
72206ecaa68aSToby Isaac     }
72216ecaa68aSToby Isaac     else {
72226ecaa68aSToby Isaac       newValues = tmpValues;
72236ecaa68aSToby Isaac     }
72246ecaa68aSToby Isaac   }
72256ecaa68aSToby Isaac 
7226d3d1a6afSToby Isaac   /* clean up */
72275f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices));
72285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
72296ecaa68aSToby Isaac 
7230d3d1a6afSToby Isaac   if (numFields) {
7231d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72325f80ce2aSJacob Faibussowitsch       CHKERRQ(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
72335f80ce2aSJacob Faibussowitsch       CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
72345f80ce2aSJacob Faibussowitsch       CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
7235d3d1a6afSToby Isaac     }
7236d3d1a6afSToby Isaac   }
7237d3d1a6afSToby Isaac   else {
72385f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
72395f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
72405f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]));
7241d3d1a6afSToby Isaac   }
72425f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(aIS,&anchors));
7243d3d1a6afSToby Isaac 
7244d3d1a6afSToby Isaac   /* output */
72456ecaa68aSToby Isaac   if (outPoints) {
7246d3d1a6afSToby Isaac     *outPoints = newPoints;
72476ecaa68aSToby Isaac   }
72486ecaa68aSToby Isaac   else {
72495f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
72506ecaa68aSToby Isaac   }
725131620726SToby Isaac   if (outValues) {
7252d3d1a6afSToby Isaac     *outValues = newValues;
72536ecaa68aSToby Isaac   }
72546ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7255d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7256d3d1a6afSToby Isaac   }
7257d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7258d3d1a6afSToby Isaac }
7259d3d1a6afSToby Isaac 
72604a1e0b3eSMatthew G. Knepley /*@C
726171f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72627cd05799SMatthew G. Knepley 
72637cd05799SMatthew G. Knepley   Not collective
72647cd05799SMatthew G. Knepley 
72657cd05799SMatthew G. Knepley   Input Parameters:
72667cd05799SMatthew G. Knepley + dm         - The DM
726771f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
726871f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
726971f0bbf9SMatthew G. Knepley . point      - The point defining the closure
727071f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
72717cd05799SMatthew G. Knepley 
727271f0bbf9SMatthew G. Knepley   Output Parameters:
727371f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
727471f0bbf9SMatthew G. Knepley . indices    - The dof indices
727571f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
727671f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
72777cd05799SMatthew G. Knepley 
727836fa2b79SJed Brown   Notes:
727936fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
728036fa2b79SJed Brown 
728136fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
728236fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
728336fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
728436fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
728536fa2b79SJed Brown   indices (with the above semantics) are implied.
72867cd05799SMatthew G. Knepley 
72877cd05799SMatthew G. Knepley   Level: advanced
72887cd05799SMatthew G. Knepley 
728936fa2b79SJed Brown .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
72904a1e0b3eSMatthew G. Knepley @*/
729171f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
729271f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
72937773e69fSMatthew G. Knepley {
729471f0bbf9SMatthew G. Knepley   /* Closure ordering */
72957773e69fSMatthew G. Knepley   PetscSection        clSection;
72967773e69fSMatthew G. Knepley   IS                  clPoints;
729771f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
729871f0bbf9SMatthew G. Knepley   PetscInt           *points;
729971f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
730071f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
73014acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
730271f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
730371f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
730471f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
730571f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
730671f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
730771f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
730871f0bbf9SMatthew G. Knepley 
730971f0bbf9SMatthew G. Knepley   PetscInt           *idx;
731071f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
731171f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
73127773e69fSMatthew G. Knepley 
731371f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
73147773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73157773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
731636fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7317*dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
731871f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
7319*dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
732071f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
73215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section, &Nf));
73222c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf);
73235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(offsets, 32));
732471f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
73255f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7326c459fbc1SJed Brown   if (useClPerm) {
7327c459fbc1SJed Brown     PetscInt depth, clsize;
73285f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetPointDepth(dm, point, &depth));
7329c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7330c459fbc1SJed Brown       PetscInt dof;
73315f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section, points[2*p], &dof));
7332c459fbc1SJed Brown       clsize += dof;
7333c459fbc1SJed Brown     }
73345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
7335c459fbc1SJed Brown   }
733671f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
733771f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
73387773e69fSMatthew G. Knepley     PetscInt dof, fdof;
73397773e69fSMatthew G. Knepley 
73405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(section, points[p], &dof));
73417773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
73425f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(section, points[p], f, &fdof));
73437773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
73447773e69fSMatthew G. Knepley     }
734571f0bbf9SMatthew G. Knepley     Ni += dof;
73467773e69fSMatthew G. Knepley   }
73477773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
73482c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni);
734971f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
735071f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73515f80ce2aSJacob Faibussowitsch     if (Nf) CHKERRQ(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73525f80ce2aSJacob Faibussowitsch     else    CHKERRQ(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
735371f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
735471f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
735571f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73566ecaa68aSToby Isaac 
735771f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
735871f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
735971f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
736071f0bbf9SMatthew G. Knepley 
73615f80ce2aSJacob Faibussowitsch         if (!Nf) CHKERRQ(PetscSectionGetDof(section, pnt, &fdof));
73625f80ce2aSJacob Faibussowitsch         else     CHKERRQ(PetscSectionGetFieldDof(section, pnt, f, &fdof));
736371f0bbf9SMatthew G. Knepley         if (flip) {
736471f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
736571f0bbf9SMatthew G. Knepley 
736671f0bbf9SMatthew G. Knepley           if (!valCopy) {
73675f80ce2aSJacob Faibussowitsch             CHKERRQ(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
736871f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
736971f0bbf9SMatthew G. Knepley             *values = valCopy;
737071f0bbf9SMatthew G. Knepley           }
737171f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
737271f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
737371f0bbf9SMatthew G. Knepley 
737471f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
737571f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
737671f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
73776ecaa68aSToby Isaac             }
73786ecaa68aSToby Isaac           }
737971f0bbf9SMatthew G. Knepley         }
738071f0bbf9SMatthew G. Knepley         foffset += fdof;
738171f0bbf9SMatthew G. Knepley       }
738271f0bbf9SMatthew G. Knepley     }
738371f0bbf9SMatthew G. Knepley   }
738471f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
73855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
738671f0bbf9SMatthew G. Knepley   if (NclC) {
73875f80ce2aSJacob Faibussowitsch     if (valCopy) CHKERRQ(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
738871f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
73895f80ce2aSJacob Faibussowitsch       if (Nf) CHKERRQ(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73905f80ce2aSJacob Faibussowitsch       else    CHKERRQ(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
739171f0bbf9SMatthew G. Knepley     }
739271f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
73935f80ce2aSJacob Faibussowitsch       if (Nf) CHKERRQ(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
73945f80ce2aSJacob Faibussowitsch       else    CHKERRQ(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
739571f0bbf9SMatthew G. Knepley     }
73965f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
739771f0bbf9SMatthew G. Knepley     Ncl     = NclC;
739871f0bbf9SMatthew G. Knepley     Ni      = NiC;
739971f0bbf9SMatthew G. Knepley     points  = pointsC;
740071f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
740171f0bbf9SMatthew G. Knepley   }
740271f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
74035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
740471f0bbf9SMatthew G. Knepley   if (Nf) {
740571f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
740671f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
740771f0bbf9SMatthew G. Knepley 
740871f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
74095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
741071f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
741171f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
741271f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
741371f0bbf9SMatthew G. Knepley 
74145f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
74157773e69fSMatthew G. Knepley       }
74167773e69fSMatthew G. Knepley     } else {
741771f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
741871f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
741971f0bbf9SMatthew G. Knepley 
74205f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(idxSection, pnt, &idxOff));
742171f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
742271f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
742371f0bbf9SMatthew G. Knepley          * global section. */
74245f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
742571f0bbf9SMatthew G. Knepley       }
742671f0bbf9SMatthew G. Knepley     }
742771f0bbf9SMatthew G. Knepley   } else {
742871f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
742971f0bbf9SMatthew G. Knepley 
743071f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
743171f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
74324acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
74334acb8e1eSToby Isaac 
74345f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(idxSection, pnt, &idxOff));
743571f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
743671f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
74375f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
74387773e69fSMatthew G. Knepley     }
74397773e69fSMatthew G. Knepley   }
744071f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
744171f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
74425f80ce2aSJacob Faibussowitsch     if (Nf) CHKERRQ(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74435f80ce2aSJacob Faibussowitsch     else    CHKERRQ(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
74444acb8e1eSToby Isaac   }
744571f0bbf9SMatthew G. Knepley   if (NclC) {
74465f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC));
74477773e69fSMatthew G. Knepley   } else {
74485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
74497773e69fSMatthew G. Knepley   }
745071f0bbf9SMatthew G. Knepley 
745171f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
745271f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
74537773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74547773e69fSMatthew G. Knepley }
74557773e69fSMatthew G. Knepley 
74567cd05799SMatthew G. Knepley /*@C
745771f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74587cd05799SMatthew G. Knepley 
74597cd05799SMatthew G. Knepley   Not collective
74607cd05799SMatthew G. Knepley 
74617cd05799SMatthew G. Knepley   Input Parameters:
74627cd05799SMatthew G. Knepley + dm         - The DM
746371f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
746471f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
746571f0bbf9SMatthew G. Knepley . point      - The point defining the closure
746671f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
746771f0bbf9SMatthew G. Knepley 
746871f0bbf9SMatthew G. Knepley   Output Parameters:
746971f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
747071f0bbf9SMatthew G. Knepley . indices    - The dof indices
747171f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
747271f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
747371f0bbf9SMatthew G. Knepley 
747471f0bbf9SMatthew G. Knepley   Notes:
747571f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
747671f0bbf9SMatthew G. Knepley 
747771f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
747871f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
747971f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
748071f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
748171f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
74827cd05799SMatthew G. Knepley 
74837cd05799SMatthew G. Knepley   Level: advanced
74847cd05799SMatthew G. Knepley 
748571f0bbf9SMatthew G. Knepley .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
74867cd05799SMatthew G. Knepley @*/
748771f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
748871f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
74897773e69fSMatthew G. Knepley {
74907773e69fSMatthew G. Knepley   PetscFunctionBegin;
74917773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7492064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
74935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
74947773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74957773e69fSMatthew G. Knepley }
74967773e69fSMatthew G. Knepley 
74977f5d1fdeSMatthew G. Knepley /*@C
74987f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
74997f5d1fdeSMatthew G. Knepley 
75007f5d1fdeSMatthew G. Knepley   Not collective
75017f5d1fdeSMatthew G. Knepley 
75027f5d1fdeSMatthew G. Knepley   Input Parameters:
75037f5d1fdeSMatthew G. Knepley + dm - The DM
7504ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7505ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
75067f5d1fdeSMatthew G. Knepley . A - The matrix
7507eaf898f9SPatrick Sanan . point - The point in the DM
75087f5d1fdeSMatthew G. Knepley . values - The array of values
75097f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75107f5d1fdeSMatthew G. Knepley 
75117f5d1fdeSMatthew G. Knepley   Fortran Notes:
75127f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
75137f5d1fdeSMatthew G. Knepley 
75147f5d1fdeSMatthew G. Knepley   Level: intermediate
75157f5d1fdeSMatthew G. Knepley 
75164a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
75177f5d1fdeSMatthew G. Knepley @*/
75187c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7519552f7358SJed Brown {
7520552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7521552f7358SJed Brown   PetscInt          *indices;
752271f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
752371f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7524552f7358SJed Brown   PetscErrorCode     ierr;
7525552f7358SJed Brown 
7526552f7358SJed Brown   PetscFunctionBegin;
7527552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
75285f80ce2aSJacob Faibussowitsch   if (!section) CHKERRQ(DMGetLocalSection(dm, &section));
75293dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75305f80ce2aSJacob Faibussowitsch   if (!globalSection) CHKERRQ(DMGetGlobalSection(dm, &globalSection));
75313dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
75323dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7533552f7358SJed Brown 
75345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75350d644c17SKarl Rupp 
75365f80ce2aSJacob Faibussowitsch   if (mesh->printSetValues) CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
75374a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7538552f7358SJed Brown   if (ierr) {
7539552f7358SJed Brown     PetscMPIInt    rank;
7540552f7358SJed Brown 
75415f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
75425f80ce2aSJacob Faibussowitsch     CHKERRQ((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
75435f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
75445f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75455f80ce2aSJacob Faibussowitsch     if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7546c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values");
7547552f7358SJed Brown   }
75484a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75494a1e0b3eSMatthew G. Knepley     PetscInt i;
75505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
75515f80ce2aSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]));
75525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n"));
75534a1e0b3eSMatthew G. Knepley   }
755471f0bbf9SMatthew G. Knepley 
75555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75565f80ce2aSJacob Faibussowitsch   if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
755771f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75584acb8e1eSToby Isaac }
755971f0bbf9SMatthew G. Knepley 
75604a1e0b3eSMatthew G. Knepley /*@C
75614a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75624a1e0b3eSMatthew G. Knepley 
75634a1e0b3eSMatthew G. Knepley   Not collective
75644a1e0b3eSMatthew G. Knepley 
75654a1e0b3eSMatthew G. Knepley   Input Parameters:
75664a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
75674a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
75684a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
75694a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
75704a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
75714a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
75724a1e0b3eSMatthew G. Knepley . A - The matrix
75734a1e0b3eSMatthew G. Knepley . point - The point in the DMs
75744a1e0b3eSMatthew G. Knepley . values - The array of values
75754a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75764a1e0b3eSMatthew G. Knepley 
75774a1e0b3eSMatthew G. Knepley   Level: intermediate
75784a1e0b3eSMatthew G. Knepley 
75794a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
75804a1e0b3eSMatthew G. Knepley @*/
758171f0bbf9SMatthew 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)
758271f0bbf9SMatthew G. Knepley {
758371f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
758471f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
758571f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
758671f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
758771f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
758871f0bbf9SMatthew G. Knepley 
758971f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
759071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
75915f80ce2aSJacob Faibussowitsch   if (!sectionRow) CHKERRQ(DMGetLocalSection(dmRow, &sectionRow));
759271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
75935f80ce2aSJacob Faibussowitsch   if (!globalSectionRow) CHKERRQ(DMGetGlobalSection(dmRow, &globalSectionRow));
759471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
759571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
75965f80ce2aSJacob Faibussowitsch   if (!sectionCol) CHKERRQ(DMGetLocalSection(dmCol, &sectionCol));
759771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
75985f80ce2aSJacob Faibussowitsch   if (!globalSectionCol) CHKERRQ(DMGetGlobalSection(dmCol, &globalSectionCol));
759971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
760071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
760171f0bbf9SMatthew G. Knepley 
76025f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
760471f0bbf9SMatthew G. Knepley 
76055f80ce2aSJacob Faibussowitsch   if (mesh->printSetValues) CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
76064a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
760771f0bbf9SMatthew G. Knepley   if (ierr) {
760871f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
760971f0bbf9SMatthew G. Knepley 
76105f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
76115f80ce2aSJacob Faibussowitsch     CHKERRQ((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
76125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
76135f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76145f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values));
76155f80ce2aSJacob Faibussowitsch     if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
761671f0bbf9SMatthew G. Knepley     CHKERRQ(ierr);
7617d3d1a6afSToby Isaac   }
761871f0bbf9SMatthew G. Knepley 
76195f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
76215f80ce2aSJacob Faibussowitsch   if (values != valuesOrig) CHKERRQ(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7622552f7358SJed Brown   PetscFunctionReturn(0);
7623552f7358SJed Brown }
7624552f7358SJed Brown 
7625de41b84cSMatthew 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)
7626de41b84cSMatthew G. Knepley {
7627de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7628de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7629de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7630de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
763117c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7632de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7633412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
76344ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7635de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7636de41b84cSMatthew G. Knepley 
7637de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7638de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7639de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
76405f80ce2aSJacob Faibussowitsch   if (!fsection) CHKERRQ(DMGetLocalSection(dmf, &fsection));
7641de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
76425f80ce2aSJacob Faibussowitsch   if (!csection) CHKERRQ(DMGetLocalSection(dmc, &csection));
7643de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
76445f80ce2aSJacob Faibussowitsch   if (!globalFSection) CHKERRQ(DMGetGlobalSection(dmf, &globalFSection));
7645de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
76465f80ce2aSJacob Faibussowitsch   if (!globalCSection) CHKERRQ(DMGetGlobalSection(dmc, &globalCSection));
7647de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7648de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
76495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(fsection, &numFields));
76502c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
76515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(foffsets, 32));
76525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(coffsets, 32));
7653de41b84cSMatthew G. Knepley   /* Column indices */
76545f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
76554ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7656de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7657de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
76585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(csection, &pStart, &pEnd));
7659de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7660de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7661de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7662de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7663de41b84cSMatthew G. Knepley       ++q;
7664de41b84cSMatthew G. Knepley     }
7665de41b84cSMatthew G. Knepley   }
7666de41b84cSMatthew G. Knepley   numCPoints = q;
7667de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7668de41b84cSMatthew G. Knepley     PetscInt fdof;
7669de41b84cSMatthew G. Knepley 
76705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(csection, cpoints[p], &dof));
76714ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7672de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76735f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7674de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7675de41b84cSMatthew G. Knepley     }
7676de41b84cSMatthew G. Knepley     numCIndices += dof;
7677de41b84cSMatthew G. Knepley   }
7678de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7679de41b84cSMatthew G. Knepley   /* Row indices */
76805f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dmc, point, &ct));
7681412e9a14SMatthew G. Knepley   {
7682012bc364SMatthew G. Knepley     DMPlexTransform tr;
7683012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7684012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7685012bc364SMatthew G. Knepley 
76865f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
76875f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
76885f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7689012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
76905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformDestroy(&tr));
7691412e9a14SMatthew G. Knepley   }
76925f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
7693de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7694de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
76955f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7696de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
76975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(fsection, &pStart, &pEnd));
7698de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7699de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
77005f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(fsection, fpoints[p], &dof));
77014ca5e9f5SMatthew G. Knepley         if (!dof) continue;
77024ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
77034ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7704de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7705de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7706de41b84cSMatthew G. Knepley         ++q;
7707de41b84cSMatthew G. Knepley       }
7708de41b84cSMatthew G. Knepley     }
77095f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7710de41b84cSMatthew G. Knepley   }
7711de41b84cSMatthew G. Knepley   numFPoints = q;
7712de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7713de41b84cSMatthew G. Knepley     PetscInt fdof;
7714de41b84cSMatthew G. Knepley 
77155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
77164ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7717de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77185f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
7719de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7720de41b84cSMatthew G. Knepley     }
7721de41b84cSMatthew G. Knepley     numFIndices += dof;
7722de41b84cSMatthew G. Knepley   }
7723de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7724de41b84cSMatthew G. Knepley 
77252c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
77262c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
77275f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7729de41b84cSMatthew G. Knepley   if (numFields) {
77304acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
77314acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
77324acb8e1eSToby Isaac 
77334acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77345f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7736de41b84cSMatthew G. Knepley     }
77374acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
77385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77395f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
77404acb8e1eSToby Isaac     }
77414acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
77425f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77435f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
77444acb8e1eSToby Isaac     }
77454acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77465f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7748de41b84cSMatthew G. Knepley     }
7749de41b84cSMatthew G. Knepley   } else {
77504acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77514acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77524acb8e1eSToby Isaac 
77535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
77554acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77564acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77574acb8e1eSToby Isaac 
77585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77595f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
7760de41b84cSMatthew G. Knepley     }
77614acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77624acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77634acb8e1eSToby Isaac 
77645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77655f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
7766de41b84cSMatthew G. Knepley     }
77675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
7769de41b84cSMatthew G. Knepley   }
77705f80ce2aSJacob Faibussowitsch   if (mesh->printSetValues) CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77714acb8e1eSToby Isaac   /* TODO: flips */
7772de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7773de41b84cSMatthew G. Knepley   if (ierr) {
7774de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7775de41b84cSMatthew G. Knepley 
77765f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
77775f80ce2aSJacob Faibussowitsch     CHKERRQ((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
77785f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77795f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77805f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7781de41b84cSMatthew G. Knepley     CHKERRQ(ierr);
7782de41b84cSMatthew G. Knepley   }
77835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
77845f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
77855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7787de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7788de41b84cSMatthew G. Knepley }
7789de41b84cSMatthew G. Knepley 
77907c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
77917c927364SMatthew G. Knepley {
77927c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
77937c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
77947c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
779517c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7796412e9a14SMatthew G. Knepley   DMPolytopeType ct;
77977c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
77987c927364SMatthew G. Knepley 
77997c927364SMatthew G. Knepley   PetscFunctionBegin;
78007c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
78017c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
78025f80ce2aSJacob Faibussowitsch   if (!fsection) CHKERRQ(DMGetLocalSection(dmf, &fsection));
78037c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
78045f80ce2aSJacob Faibussowitsch   if (!csection) CHKERRQ(DMGetLocalSection(dmc, &csection));
78057c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
78065f80ce2aSJacob Faibussowitsch   if (!globalFSection) CHKERRQ(DMGetGlobalSection(dmf, &globalFSection));
78077c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
78085f80ce2aSJacob Faibussowitsch   if (!globalCSection) CHKERRQ(DMGetGlobalSection(dmc, &globalCSection));
78097c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
78105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(fsection, &numFields));
78112c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
78125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(foffsets, 32));
78135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(coffsets, 32));
78147c927364SMatthew G. Knepley   /* Column indices */
78155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78167c927364SMatthew G. Knepley   maxFPoints = numCPoints;
78177c927364SMatthew G. Knepley   /* Compress out points not in the section */
78187c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
78195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(csection, &pStart, &pEnd));
78207c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
78217c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
78227c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
78237c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
78247c927364SMatthew G. Knepley       ++q;
78257c927364SMatthew G. Knepley     }
78267c927364SMatthew G. Knepley   }
78277c927364SMatthew G. Knepley   numCPoints = q;
78287c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
78297c927364SMatthew G. Knepley     PetscInt fdof;
78307c927364SMatthew G. Knepley 
78315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(csection, cpoints[p], &dof));
78327c927364SMatthew G. Knepley     if (!dof) continue;
78337c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78345f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
78357c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
78367c927364SMatthew G. Knepley     }
78377c927364SMatthew G. Knepley     numCIndices += dof;
78387c927364SMatthew G. Knepley   }
78397c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
78407c927364SMatthew G. Knepley   /* Row indices */
78415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dmc, point, &ct));
7842412e9a14SMatthew G. Knepley   {
7843012bc364SMatthew G. Knepley     DMPlexTransform tr;
7844012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7845012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7846012bc364SMatthew G. Knepley 
78475f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
78485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
78495f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7850012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
78515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexTransformDestroy(&tr));
7852412e9a14SMatthew G. Knepley   }
78535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
78547c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78557c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78565f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
78577c927364SMatthew G. Knepley     /* Compress out points not in the section */
78585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(fsection, &pStart, &pEnd));
78597c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
78607c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78615f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(fsection, fpoints[p], &dof));
78627c927364SMatthew G. Knepley         if (!dof) continue;
78637c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
78647c927364SMatthew G. Knepley         if (s < q) continue;
78657c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
78667c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
78677c927364SMatthew G. Knepley         ++q;
78687c927364SMatthew G. Knepley       }
78697c927364SMatthew G. Knepley     }
78705f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
78717c927364SMatthew G. Knepley   }
78727c927364SMatthew G. Knepley   numFPoints = q;
78737c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
78747c927364SMatthew G. Knepley     PetscInt fdof;
78757c927364SMatthew G. Knepley 
78765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
78777c927364SMatthew G. Knepley     if (!dof) continue;
78787c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78795f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
78807c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
78817c927364SMatthew G. Knepley     }
78827c927364SMatthew G. Knepley     numFIndices += dof;
78837c927364SMatthew G. Knepley   }
78847c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
78857c927364SMatthew G. Knepley 
78862c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
78872c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
78887c927364SMatthew G. Knepley   if (numFields) {
78894acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
78904acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
78914acb8e1eSToby Isaac 
78924acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
78935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
78945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
78957c927364SMatthew G. Knepley     }
78964acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
78975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
78985f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
78994acb8e1eSToby Isaac     }
79004acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
79015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79025f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
79034acb8e1eSToby Isaac     }
79044acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79055f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79065f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79077c927364SMatthew G. Knepley     }
79087c927364SMatthew G. Knepley   } else {
79094acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
79104acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
79114acb8e1eSToby Isaac 
79125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79144acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
79154acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
79164acb8e1eSToby Isaac 
79175f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79185f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
79197c927364SMatthew G. Knepley     }
79204acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
79214acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
79224acb8e1eSToby Isaac 
79235f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79245f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
79257c927364SMatthew G. Knepley     }
79265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79287c927364SMatthew G. Knepley   }
79295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
79305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79317c927364SMatthew G. Knepley   PetscFunctionReturn(0);
79327c927364SMatthew G. Knepley }
79337c927364SMatthew G. Knepley 
79347cd05799SMatthew G. Knepley /*@C
79357cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
79367cd05799SMatthew G. Knepley 
79377cd05799SMatthew G. Knepley   Input Parameter:
79387cd05799SMatthew G. Knepley . dm   - The DMPlex object
79397cd05799SMatthew G. Knepley 
79407cd05799SMatthew G. Knepley   Output Parameter:
79417cd05799SMatthew G. Knepley . cellHeight - The height of a cell
79427cd05799SMatthew G. Knepley 
79437cd05799SMatthew G. Knepley   Level: developer
79447cd05799SMatthew G. Knepley 
79457cd05799SMatthew G. Knepley .seealso DMPlexSetVTKCellHeight()
79467cd05799SMatthew G. Knepley @*/
7947552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7948552f7358SJed Brown {
7949552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7950552f7358SJed Brown 
7951552f7358SJed Brown   PetscFunctionBegin;
7952552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7953*dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
7954552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7955552f7358SJed Brown   PetscFunctionReturn(0);
7956552f7358SJed Brown }
7957552f7358SJed Brown 
79587cd05799SMatthew G. Knepley /*@C
79597cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79607cd05799SMatthew G. Knepley 
79617cd05799SMatthew G. Knepley   Input Parameters:
79627cd05799SMatthew G. Knepley + dm   - The DMPlex object
79637cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79647cd05799SMatthew G. Knepley 
79657cd05799SMatthew G. Knepley   Level: developer
79667cd05799SMatthew G. Knepley 
79677cd05799SMatthew G. Knepley .seealso DMPlexGetVTKCellHeight()
79687cd05799SMatthew G. Knepley @*/
7969552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
7970552f7358SJed Brown {
7971552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7972552f7358SJed Brown 
7973552f7358SJed Brown   PetscFunctionBegin;
7974552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7975552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7976552f7358SJed Brown   PetscFunctionReturn(0);
7977552f7358SJed Brown }
7978552f7358SJed Brown 
7979e6139122SMatthew G. Knepley /*@
7980e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
7981e6139122SMatthew G. Knepley 
7982e6139122SMatthew G. Knepley   Input Parameter:
7983e6139122SMatthew G. Knepley . dm - The DMPlex object
7984e6139122SMatthew G. Knepley 
7985e6139122SMatthew G. Knepley   Output Parameters:
79862a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
79872a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
7988e6139122SMatthew G. Knepley 
79892a9f31c0SMatthew G. Knepley   Level: advanced
7990e6139122SMatthew G. Knepley 
79918065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
7992e6139122SMatthew G. Knepley @*/
7993e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
7994e6139122SMatthew G. Knepley {
7995412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
7996e6139122SMatthew G. Knepley 
7997e6139122SMatthew G. Knepley   PetscFunctionBegin;
7998e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79995f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellTypeLabel(dm, &ctLabel));
80005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8001e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
8002e6139122SMatthew G. Knepley }
8003e6139122SMatthew G. Knepley 
80049886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8005552f7358SJed Brown {
8006552f7358SJed Brown   PetscSection   section, globalSection;
8007552f7358SJed Brown   PetscInt      *numbers, p;
8008552f7358SJed Brown 
8009552f7358SJed Brown   PetscFunctionBegin;
80105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
80115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(section, pStart, pEnd));
8012552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(section, p, 1));
8014552f7358SJed Brown   }
80155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(section));
80165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
80175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(pEnd - pStart, &numbers));
8018552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80195f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]));
8020ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
8021ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
8022552f7358SJed Brown   }
80235f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8024ef48cebcSMatthew G. Knepley   if (globalSize) {
8025ef48cebcSMatthew G. Knepley     PetscLayout layout;
80265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout));
80275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutGetSize(layout, globalSize));
80285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutDestroy(&layout));
8029ef48cebcSMatthew G. Knepley   }
80305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&section));
80315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&globalSection));
8032552f7358SJed Brown   PetscFunctionReturn(0);
8033552f7358SJed Brown }
8034552f7358SJed Brown 
803581ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8036552f7358SJed Brown {
8037412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
8038552f7358SJed Brown 
8039552f7358SJed Brown   PetscFunctionBegin;
80405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight));
80415f80ce2aSJacob Faibussowitsch   if (includeHybrid) CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
80425f80ce2aSJacob Faibussowitsch   else               CHKERRQ(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
80435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
804481ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8045552f7358SJed Brown }
804681ed3555SMatthew G. Knepley 
80478dab3259SMatthew G. Knepley /*@
80487cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
80497cd05799SMatthew G. Knepley 
80507cd05799SMatthew G. Knepley   Input Parameter:
80517cd05799SMatthew G. Knepley . dm   - The DMPlex object
80527cd05799SMatthew G. Knepley 
80537cd05799SMatthew G. Knepley   Output Parameter:
80547cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80557cd05799SMatthew G. Knepley 
80567cd05799SMatthew G. Knepley   Level: developer
80577cd05799SMatthew G. Knepley 
80587cd05799SMatthew G. Knepley .seealso DMPlexGetVertexNumbering()
80597cd05799SMatthew G. Knepley @*/
806081ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
806181ed3555SMatthew G. Knepley {
806281ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
806381ed3555SMatthew G. Knepley 
806481ed3555SMatthew G. Knepley   PetscFunctionBegin;
806581ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80665f80ce2aSJacob Faibussowitsch   if (!mesh->globalCellNumbers) CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8067552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8068552f7358SJed Brown   PetscFunctionReturn(0);
8069552f7358SJed Brown }
8070552f7358SJed Brown 
807181ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
807281ed3555SMatthew G. Knepley {
8073412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
807481ed3555SMatthew G. Knepley 
807581ed3555SMatthew G. Knepley   PetscFunctionBegin;
807681ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80775f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
80785f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
807981ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
808081ed3555SMatthew G. Knepley }
808181ed3555SMatthew G. Knepley 
80828dab3259SMatthew G. Knepley /*@
80836aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
80847cd05799SMatthew G. Knepley 
80857cd05799SMatthew G. Knepley   Input Parameter:
80867cd05799SMatthew G. Knepley . dm   - The DMPlex object
80877cd05799SMatthew G. Knepley 
80887cd05799SMatthew G. Knepley   Output Parameter:
80897cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
80907cd05799SMatthew G. Knepley 
80917cd05799SMatthew G. Knepley   Level: developer
80927cd05799SMatthew G. Knepley 
80937cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
80947cd05799SMatthew G. Knepley @*/
8095552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8096552f7358SJed Brown {
8097552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
8098552f7358SJed Brown 
8099552f7358SJed Brown   PetscFunctionBegin;
8100552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81015f80ce2aSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) CHKERRQ(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8102552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8103552f7358SJed Brown   PetscFunctionReturn(0);
8104552f7358SJed Brown }
8105552f7358SJed Brown 
81068dab3259SMatthew G. Knepley /*@
81077cd05799SMatthew G. Knepley   DMPlexCreatePointNumbering - Create a global numbering for all points on this process
81087cd05799SMatthew G. Knepley 
81097cd05799SMatthew G. Knepley   Input Parameter:
81107cd05799SMatthew G. Knepley . dm   - The DMPlex object
81117cd05799SMatthew G. Knepley 
81127cd05799SMatthew G. Knepley   Output Parameter:
81137cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
81147cd05799SMatthew G. Knepley 
81157cd05799SMatthew G. Knepley   Level: developer
81167cd05799SMatthew G. Knepley 
81177cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
81187cd05799SMatthew G. Knepley @*/
8119ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8120ef48cebcSMatthew G. Knepley {
8121ef48cebcSMatthew G. Knepley   IS             nums[4];
8122862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
8123ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
8124ef48cebcSMatthew G. Knepley 
8125ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8126ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81275f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
81288abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
81295f80ce2aSJacob Faibussowitsch   if (depth < 0) CHKERRQ(DMGetDimension(dm, &depth));
8130862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8131862913ffSStefano Zampini     PetscInt end;
8132862913ffSStefano Zampini 
8133862913ffSStefano Zampini     depths[d] = depth-d;
81345f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
8135862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
8136862913ffSStefano Zampini   }
81375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortIntWithArray(depth+1, starts, depths));
81385f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm)));
8139862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
81402c71b3e2SJacob Faibussowitsch     PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]);
8141862913ffSStefano Zampini   }
8142ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8143ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8144ef48cebcSMatthew G. Knepley 
81455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
81465f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8147ef48cebcSMatthew G. Knepley     shift += gsize;
8148ef48cebcSMatthew G. Knepley   }
81495f80ce2aSJacob Faibussowitsch   CHKERRQ(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers));
81505f80ce2aSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) CHKERRQ(ISDestroy(&nums[d]));
8151ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8152ef48cebcSMatthew G. Knepley }
8153ef48cebcSMatthew G. Knepley 
815408a22f4bSMatthew G. Knepley /*@
815508a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
815608a22f4bSMatthew G. Knepley 
815708a22f4bSMatthew G. Knepley   Input Parameter:
815808a22f4bSMatthew G. Knepley . dm - The DMPlex object
815908a22f4bSMatthew G. Knepley 
816008a22f4bSMatthew G. Knepley   Output Parameter:
816108a22f4bSMatthew G. Knepley . ranks - The rank field
816208a22f4bSMatthew G. Knepley 
816308a22f4bSMatthew G. Knepley   Options Database Keys:
816408a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
816508a22f4bSMatthew G. Knepley 
816608a22f4bSMatthew G. Knepley   Level: intermediate
816708a22f4bSMatthew G. Knepley 
816808a22f4bSMatthew G. Knepley .seealso: DMView()
816908a22f4bSMatthew G. Knepley @*/
817008a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
817108a22f4bSMatthew G. Knepley {
817208a22f4bSMatthew G. Knepley   DM             rdm;
817308a22f4bSMatthew G. Knepley   PetscFE        fe;
817408a22f4bSMatthew G. Knepley   PetscScalar   *r;
817508a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8176a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
817708a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8178a55f9a55SMatthew G. Knepley   PetscBool      simplex;
817908a22f4bSMatthew G. Knepley 
818008a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8181f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8182f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
81835f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
81845f80ce2aSJacob Faibussowitsch   CHKERRQ(DMClone(dm, &rdm));
81855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(rdm, &dim));
81865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
81875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetCellType(dm, cStart, &ct));
8188a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
81895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
81905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) fe, "rank"));
81915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetField(rdm, 0, NULL, (PetscObject) fe));
81925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFEDestroy(&fe));
81935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateDS(rdm));
81945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(rdm, ranks));
81955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *ranks, "partition"));
81965f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(*ranks, &r));
819708a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
819808a22f4bSMatthew G. Knepley     PetscScalar *lr;
819908a22f4bSMatthew G. Knepley 
82005f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPointGlobalRef(rdm, c, r, &lr));
820171f09efeSPierre Jolivet     if (lr) *lr = rank;
820208a22f4bSMatthew G. Knepley   }
82035f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(*ranks, &r));
82045f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&rdm));
820508a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
820608a22f4bSMatthew G. Knepley }
820708a22f4bSMatthew G. Knepley 
8208ca8062c8SMatthew G. Knepley /*@
820918e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
821018e14f0cSMatthew G. Knepley 
821118e14f0cSMatthew G. Knepley   Input Parameters:
821218e14f0cSMatthew G. Knepley + dm    - The DMPlex
821318e14f0cSMatthew G. Knepley - label - The DMLabel
821418e14f0cSMatthew G. Knepley 
821518e14f0cSMatthew G. Knepley   Output Parameter:
821618e14f0cSMatthew G. Knepley . val - The label value field
821718e14f0cSMatthew G. Knepley 
821818e14f0cSMatthew G. Knepley   Options Database Keys:
821918e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
822018e14f0cSMatthew G. Knepley 
822118e14f0cSMatthew G. Knepley   Level: intermediate
822218e14f0cSMatthew G. Knepley 
822318e14f0cSMatthew G. Knepley .seealso: DMView()
822418e14f0cSMatthew G. Knepley @*/
822518e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
822618e14f0cSMatthew G. Knepley {
822718e14f0cSMatthew G. Knepley   DM             rdm;
822818e14f0cSMatthew G. Knepley   PetscFE        fe;
822918e14f0cSMatthew G. Knepley   PetscScalar   *v;
823018e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
823118e14f0cSMatthew G. Knepley 
823218e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
823318e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
823418e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
823518e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
82365f80ce2aSJacob Faibussowitsch   CHKERRQ(DMClone(dm, &rdm));
82375f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(rdm, &dim));
82385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
82395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) fe, "label_value"));
82405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFEDestroy(&fe));
82425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateDS(rdm));
82435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82445f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(rdm, val));
82455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *val, "label_value"));
82465f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(*val, &v));
824718e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
824818e14f0cSMatthew G. Knepley     PetscScalar *lv;
824918e14f0cSMatthew G. Knepley     PetscInt     cval;
825018e14f0cSMatthew G. Knepley 
82515f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPointGlobalRef(rdm, c, v, &lv));
82525f80ce2aSJacob Faibussowitsch     CHKERRQ(DMLabelGetValue(label, c, &cval));
825318e14f0cSMatthew G. Knepley     *lv = cval;
825418e14f0cSMatthew G. Knepley   }
82555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(*val, &v));
82565f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&rdm));
825718e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
825818e14f0cSMatthew G. Knepley }
825918e14f0cSMatthew G. Knepley 
826018e14f0cSMatthew G. Knepley /*@
8261ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8262ca8062c8SMatthew G. Knepley 
826369916449SMatthew G. Knepley   Input Parameter:
826469916449SMatthew G. Knepley . dm - The DMPlex object
8265ca8062c8SMatthew G. Knepley 
826695eb5ee5SVaclav Hapla   Notes:
826795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
826895eb5ee5SVaclav Hapla 
826995eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8270ca8062c8SMatthew G. Knepley 
8271ca8062c8SMatthew G. Knepley   Level: developer
8272ca8062c8SMatthew G. Knepley 
827395eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8274ca8062c8SMatthew G. Knepley @*/
8275ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8276ca8062c8SMatthew G. Knepley {
8277ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8278ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8279ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
828057beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
828157beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8282ca8062c8SMatthew G. Knepley 
8283ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8284ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
82855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
82865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetConeSection(dm, &coneSection));
82875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSupportSection(dm, &supportSection));
8288ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
82895f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
8290ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
82915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, p, &coneSize));
82925f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, p, &cone));
8293ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
829442e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
829542e66dfaSMatthew G. Knepley       PetscInt  d;
829642e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
829742e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
829842e66dfaSMatthew G. Knepley       }
82995f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupportSize(dm, cone[c], &supportSize));
83005f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetSupport(dm, cone[c], &support));
8301ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8302ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8303ca8062c8SMatthew G. Knepley       }
830442e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
83055f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p));
8306ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
83075f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]));
8308ca8062c8SMatthew G. Knepley         }
83095f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n"));
83105f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]));
8311ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
83125f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]));
8313ca8062c8SMatthew G. Knepley         }
83145f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n"));
831528b400f6SJacob Faibussowitsch         PetscCheck(!dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]);
831698921bdaSJacob Faibussowitsch         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]);
8317ca8062c8SMatthew G. Knepley       }
831842e66dfaSMatthew G. Knepley     }
83195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTreeParent(dm, p, &pp, NULL));
832057beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
83215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupportSize(dm, p, &supportSize));
83225f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSupport(dm, p, &support));
8323ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
83245f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, support[s], &coneSize));
83255f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, support[s], &cone));
8326ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
83275f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
832857beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8329ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8330ca8062c8SMatthew G. Knepley       }
8331ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
83325f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p));
8333ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
83345f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]));
8335ca8062c8SMatthew G. Knepley         }
83365f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n"));
83375f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]));
8338ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
83395f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]));
8340ca8062c8SMatthew G. Knepley         }
83415f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n"));
834298921bdaSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]);
8343ca8062c8SMatthew G. Knepley       }
8344ca8062c8SMatthew G. Knepley     }
8345ca8062c8SMatthew G. Knepley   }
834657beb4faSStefano Zampini   if (storagecheck) {
83475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(coneSection, &csize));
83485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetStorageSize(supportSection, &ssize));
83492c71b3e2SJacob Faibussowitsch     PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize);
835057beb4faSStefano Zampini   }
8351ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8352ca8062c8SMatthew G. Knepley }
8353ca8062c8SMatthew G. Knepley 
8354412e9a14SMatthew G. Knepley /*
8355412e9a14SMatthew 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.
8356412e9a14SMatthew G. Knepley */
8357412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8358412e9a14SMatthew G. Knepley {
8359412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8360412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8361412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8362412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8363412e9a14SMatthew G. Knepley 
8364412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8365412e9a14SMatthew G. Knepley   *unsplit = 0;
8366412e9a14SMatthew G. Knepley   switch (ct) {
8367b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
8368b5a892a1SMatthew G. Knepley       ptpoints[npt++] = c;
8369b5a892a1SMatthew G. Knepley       break;
8370412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
83715f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, c, &cone));
83725f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize));
8373412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
83745f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCellType(dm, cone[cp], &cct));
8375412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8376412e9a14SMatthew G. Knepley       }
8377412e9a14SMatthew G. Knepley       break;
8378412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8379412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
83805f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, c, &cone));
83815f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize));
8382412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
83835f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCone(dm, cone[cp], &ccone));
83845f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8385412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
83865f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetCellType(dm, ccone[ccp], &cct));
8387412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8388412e9a14SMatthew G. Knepley             PetscInt p;
8389412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8390412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8391412e9a14SMatthew G. Knepley           }
8392412e9a14SMatthew G. Knepley         }
8393412e9a14SMatthew G. Knepley       }
8394412e9a14SMatthew G. Knepley       break;
8395412e9a14SMatthew G. Knepley     default: break;
8396412e9a14SMatthew G. Knepley   }
8397412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
83985f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8399412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8400412e9a14SMatthew G. Knepley   }
8401412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8402412e9a14SMatthew G. Knepley }
8403412e9a14SMatthew G. Knepley 
8404ca8062c8SMatthew G. Knepley /*@
8405ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8406ca8062c8SMatthew G. Knepley 
8407ca8062c8SMatthew G. Knepley   Input Parameters:
8408ca8062c8SMatthew G. Knepley + dm - The DMPlex object
840958723a97SMatthew G. Knepley - cellHeight - Normally 0
8410ca8062c8SMatthew G. Knepley 
841195eb5ee5SVaclav Hapla   Notes:
841295eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
841325c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8414ca8062c8SMatthew G. Knepley 
841595eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
841695eb5ee5SVaclav Hapla 
8417ca8062c8SMatthew G. Knepley   Level: developer
8418ca8062c8SMatthew G. Knepley 
841995eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8420ca8062c8SMatthew G. Knepley @*/
842125c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8422ca8062c8SMatthew G. Knepley {
8423412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8424412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8425412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8426ca8062c8SMatthew G. Knepley 
8427ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8428ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsInterpolated(dm, &interp));
84305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
84315f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8432412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8433412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8434412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
843558723a97SMatthew G. Knepley 
84365f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, c, &ct));
84372c71b3e2SJacob Faibussowitsch     PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c);
8438412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8439412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
84405f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize));
84412c71b3e2SJacob 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));
8442412e9a14SMatthew G. Knepley     }
84435f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
844458723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
844558723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8446412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
844758723a97SMatthew G. Knepley     }
84485f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8449412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8450412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8451412e9a14SMatthew G. Knepley       PetscInt unsplit;
845242363296SMatthew G. Knepley 
84535f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8454412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
845542363296SMatthew G. Knepley     }
84562c71b3e2SJacob 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));
845742363296SMatthew G. Knepley   }
8458ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8459ca8062c8SMatthew G. Knepley }
84609bf0dad6SMatthew G. Knepley 
84619bf0dad6SMatthew G. Knepley /*@
84629bf0dad6SMatthew 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
84639bf0dad6SMatthew G. Knepley 
8464899ea2b8SJacob Faibussowitsch   Not Collective
8465899ea2b8SJacob Faibussowitsch 
84669bf0dad6SMatthew G. Knepley   Input Parameters:
84679bf0dad6SMatthew G. Knepley + dm - The DMPlex object
84689bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
84699bf0dad6SMatthew G. Knepley 
847045da879fSVaclav Hapla   Notes:
847145da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
847245da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
847345da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
847445da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
84759bf0dad6SMatthew G. Knepley 
847695eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
847795eb5ee5SVaclav Hapla 
84789bf0dad6SMatthew G. Knepley   Level: developer
84799bf0dad6SMatthew G. Knepley 
848095eb5ee5SVaclav Hapla .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions()
84819bf0dad6SMatthew G. Knepley @*/
848225c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
84839bf0dad6SMatthew G. Knepley {
8484ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8485899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
84869bf0dad6SMatthew G. Knepley 
84879bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
84889bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84895f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsInterpolated(dm, &interpEnum));
849045da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
849145da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) {
8492899ea2b8SJacob Faibussowitsch     PetscMPIInt rank;
8493899ea2b8SJacob Faibussowitsch     MPI_Comm    comm;
8494899ea2b8SJacob Faibussowitsch 
84955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
84965f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(comm, &rank));
849798921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank);
8498899ea2b8SJacob Faibussowitsch   }
8499899ea2b8SJacob Faibussowitsch 
85005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
85015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
85025f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8503ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
85045f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
85053554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8506412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8507412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8508ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8509412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8510412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
85119bf0dad6SMatthew G. Knepley 
85125f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCellType(dm, c, &ct));
85135f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8514412e9a14SMatthew G. Knepley       if (unsplit) continue;
85155f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeSize(dm, c, &coneSize));
85165f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetCone(dm, c, &cone));
85175f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetConeOrientation(dm, c, &ornt));
85185f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85199bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
85209bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
85219bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
85229bf0dad6SMatthew G. Knepley       }
85235f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85242c71b3e2SJacob 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);
85259bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8526d4961f80SStefano Zampini         DMPolytopeType fct;
85279bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
85289bf0dad6SMatthew G. Knepley 
85295f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCellType(dm, cone[f], &fct));
85305f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
85319bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
85329bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85339bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85349bf0dad6SMatthew G. Knepley         }
85352c71b3e2SJacob 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]);
85369bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8537b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff+v]) {
8538b5a892a1SMatthew G. Knepley             PetscInt v1;
8539b5a892a1SMatthew G. Knepley 
85405f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
85415f80ce2aSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]));
85425f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
85435f80ce2aSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) CHKERRQ(PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]));
85445f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscPrintf(PETSC_COMM_SELF, "\n"));
854598921bdaSJacob 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]);
8546b5a892a1SMatthew G. Knepley           }
85479bf0dad6SMatthew G. Knepley         }
85485f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8549412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
85509bf0dad6SMatthew G. Knepley       }
85515f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85525f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85539bf0dad6SMatthew G. Knepley     }
85543554e41dSMatthew G. Knepley   }
8555552f7358SJed Brown   PetscFunctionReturn(0);
8556552f7358SJed Brown }
85573913d7c8SMatthew G. Knepley 
8558bb6a34a8SMatthew G. Knepley /*@
8559bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8560bb6a34a8SMatthew G. Knepley 
8561bb6a34a8SMatthew G. Knepley   Input Parameter:
8562bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8563bb6a34a8SMatthew G. Knepley 
856495eb5ee5SVaclav Hapla   Notes:
856595eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
856695eb5ee5SVaclav Hapla 
856795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8568bb6a34a8SMatthew G. Knepley 
8569bb6a34a8SMatthew G. Knepley   Level: developer
8570bb6a34a8SMatthew G. Knepley 
857195eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8572bb6a34a8SMatthew G. Knepley @*/
8573bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8574bb6a34a8SMatthew G. Knepley {
8575a2a9e04cSMatthew G. Knepley   Vec            coordinates;
8576bb6a34a8SMatthew G. Knepley   PetscReal      detJ, J[9], refVol = 1.0;
8577bb6a34a8SMatthew G. Knepley   PetscReal      vol;
8578412e9a14SMatthew G. Knepley   PetscBool      periodic;
857951a74b61SMatthew G. Knepley   PetscInt       dim, depth, dE, d, cStart, cEnd, c;
8580bb6a34a8SMatthew G. Knepley 
8581bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
85825f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &dim));
85835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm, &dE));
858451a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
85855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dm, &depth));
85865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL));
8587bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
85885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8589a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
85905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocal(dm, &coordinates));
8591412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8592412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8593412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8594412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8595412e9a14SMatthew G. Knepley 
85965f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCellType(dm, c, &ct));
8597412e9a14SMatthew G. Knepley     switch (ct) {
8598412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8599412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8600412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8601412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8602412e9a14SMatthew G. Knepley       default: break;
8603412e9a14SMatthew G. Knepley     }
8604412e9a14SMatthew G. Knepley     switch (ct) {
8605412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8606412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8607412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8608a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8609412e9a14SMatthew G. Knepley         continue;
8610412e9a14SMatthew G. Knepley       default: break;
8611412e9a14SMatthew G. Knepley     }
86125f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8613412e9a14SMatthew G. Knepley     if (unsplit) continue;
86145f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
86152c71b3e2SJacob 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);
86165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol));
8617412e9a14SMatthew G. Knepley     if (depth > 1 && !periodic) {
86185f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
86192c71b3e2SJacob 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);
86205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol));
8621bb6a34a8SMatthew G. Knepley     }
8622bb6a34a8SMatthew G. Knepley   }
8623bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8624bb6a34a8SMatthew G. Knepley }
8625bb6a34a8SMatthew G. Knepley 
862603da9461SVaclav Hapla /*@
8627e83a0d2dSVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex.
862803da9461SVaclav Hapla 
862903da9461SVaclav Hapla   Input Parameters:
863003da9461SVaclav Hapla . dm - The DMPlex object
863103da9461SVaclav Hapla 
8632e83a0d2dSVaclav Hapla   Notes:
8633e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
86348918e3e2SVaclav Hapla   It currently checks only meshes with no partition overlapping.
863503da9461SVaclav Hapla 
863695eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
863795eb5ee5SVaclav Hapla 
863803da9461SVaclav Hapla   Level: developer
863903da9461SVaclav Hapla 
864095eb5ee5SVaclav Hapla .seealso: DMGetPointSF(), DMSetFromOptions()
864103da9461SVaclav Hapla @*/
864203da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm)
864303da9461SVaclav Hapla {
8644f0cfc026SVaclav Hapla   PetscSF         pointSF;
8645f5869d18SMatthew G. Knepley   PetscInt        cellHeight, cStart, cEnd, l, nleaves, nroots, overlap;
8646f5869d18SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
8647f0cfc026SVaclav Hapla   PetscBool       distributed;
864803da9461SVaclav Hapla 
864903da9461SVaclav Hapla   PetscFunctionBegin;
865003da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(dm, &pointSF));
86525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexIsDistributed(dm, &distributed));
8653f0cfc026SVaclav Hapla   if (!distributed) PetscFunctionReturn(0);
86545f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetOverlap(dm, &overlap));
8655f0cfc026SVaclav Hapla   if (overlap) {
86565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping"));
86578918e3e2SVaclav Hapla     PetscFunctionReturn(0);
86588918e3e2SVaclav Hapla   }
865928b400f6SJacob Faibussowitsch   PetscCheck(pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached");
86605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL));
86612c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set");
86625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
86635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
866403da9461SVaclav Hapla 
8665ece87651SVaclav Hapla   /* 1) check there are no faces in 2D, cells in 3D, in interface */
86665f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight));
86675f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
8668f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8669f5869d18SMatthew G. Knepley     const PetscInt point = locals[l];
8670f5869d18SMatthew G. Knepley 
86712c71b3e2SJacob Faibussowitsch     PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point);
867203da9461SVaclav Hapla   }
8673ece87651SVaclav Hapla 
8674f5869d18SMatthew G. Knepley   /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
8675f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8676f5869d18SMatthew G. Knepley     const PetscInt  point = locals[l];
8677f5869d18SMatthew G. Knepley     const PetscInt *cone;
8678f5869d18SMatthew G. Knepley     PetscInt        coneSize, c, idx;
8679f5869d18SMatthew G. Knepley 
86805f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetConeSize(dm, point, &coneSize));
86815f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetCone(dm, point, &cone));
8682f5869d18SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
8683f5869d18SMatthew G. Knepley       if (!rootdegree[cone[c]]) {
86845f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFindInt(cone[c], nleaves, locals, &idx));
86852c71b3e2SJacob Faibussowitsch         PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]);
8686f5869d18SMatthew G. Knepley       }
8687f5869d18SMatthew G. Knepley     }
8688ece87651SVaclav Hapla   }
868903da9461SVaclav Hapla   PetscFunctionReturn(0);
869003da9461SVaclav Hapla }
869103da9461SVaclav Hapla 
8692b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight)
8693b5a892a1SMatthew G. Knepley {
8694b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
86955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCheckSymmetry(dm));
86965f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCheckSkeleton(dm, cellHeight));
86975f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCheckFaces(dm, cellHeight));
86985f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCheckGeometry(dm));
86995f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCheckPointSF(dm));
87005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCheckInterfaceCones(dm));
8701b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8702b5a892a1SMatthew G. Knepley }
8703b5a892a1SMatthew G. Knepley 
8704068a5610SStefano Zampini typedef struct cell_stats
8705068a5610SStefano Zampini {
8706068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8707068a5610SStefano Zampini   PetscInt  count;
8708068a5610SStefano Zampini } cell_stats_t;
8709068a5610SStefano Zampini 
871025befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8711068a5610SStefano Zampini {
8712068a5610SStefano Zampini   PetscInt i, N = *len;
8713068a5610SStefano Zampini 
8714068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8715068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8716068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8717068a5610SStefano Zampini 
8718068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8719068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8720068a5610SStefano Zampini     B->sum += A->sum;
8721068a5610SStefano Zampini     B->squaresum += A->squaresum;
8722068a5610SStefano Zampini     B->count += A->count;
8723068a5610SStefano Zampini   }
8724068a5610SStefano Zampini }
8725068a5610SStefano Zampini 
8726068a5610SStefano Zampini /*@
872743fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8728068a5610SStefano Zampini 
87298261a58bSMatthew G. Knepley   Collective on dm
87308261a58bSMatthew G. Knepley 
8731068a5610SStefano Zampini   Input Parameters:
8732068a5610SStefano Zampini + dm        - The DMPlex object
873343fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
873443fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8735068a5610SStefano Zampini 
873695eb5ee5SVaclav Hapla   Notes:
873795eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
873895eb5ee5SVaclav Hapla 
873995eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8740068a5610SStefano Zampini 
8741068a5610SStefano Zampini   Level: developer
8742068a5610SStefano Zampini 
8743f108dbd7SJacob Faibussowitsch .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality()
8744068a5610SStefano Zampini @*/
874543fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8746068a5610SStefano Zampini {
8747068a5610SStefano Zampini   DM             dmCoarse;
874843fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
874943fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
875043fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
875143fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8752412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
875343fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8754068a5610SStefano Zampini 
8755068a5610SStefano Zampini   PetscFunctionBegin;
8756068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8757068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8758068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8759068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8760068a5610SStefano Zampini   stats.count = 0;
8761068a5610SStefano Zampini 
87625f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
87635f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
87645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDim(dm,&cdim));
87655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
87665f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd));
87675f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd));
8768412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8769068a5610SStefano Zampini     PetscInt  i;
8770068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8771068a5610SStefano Zampini 
87725f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ));
87732c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c);
877443fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8775068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8776068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8777068a5610SStefano Zampini     }
8778068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8779068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8780068a5610SStefano Zampini 
8781068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8782068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8783068a5610SStefano Zampini     stats.sum       += cond;
8784068a5610SStefano Zampini     stats.squaresum += cond2;
8785068a5610SStefano Zampini     stats.count++;
87868261a58bSMatthew G. Knepley     if (output && cond > limit) {
878743fa8764SMatthew G. Knepley       PetscSection coordSection;
878843fa8764SMatthew G. Knepley       Vec          coordsLocal;
878943fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
879043fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
879143fa8764SMatthew G. Knepley 
87925f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinatesLocal(dm, &coordsLocal));
87935f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinateSection(dm, &coordSection));
87945f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
87955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond));
879643fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
87975f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSynchronizedPrintf(comm, "  Vertex %D: (", i));
879843fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
87995f80ce2aSJacob Faibussowitsch           if (d > 0) CHKERRQ(PetscSynchronizedPrintf(comm, ", "));
88005f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d])));
880143fa8764SMatthew G. Knepley         }
88025f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSynchronizedPrintf(comm, ")\n"));
880343fa8764SMatthew G. Knepley       }
88045f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
880543fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
880643fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
880743fa8764SMatthew G. Knepley 
880843fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
880943fa8764SMatthew G. Knepley           PetscReal len;
881043fa8764SMatthew G. Knepley 
88115f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
88125f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSynchronizedPrintf(comm, "  Edge %D: length %g\n", edge, (double) len));
881343fa8764SMatthew G. Knepley         }
881443fa8764SMatthew G. Knepley       }
88155f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
88165f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
881743fa8764SMatthew G. Knepley     }
8818068a5610SStefano Zampini   }
88195f80ce2aSJacob Faibussowitsch   if (output) CHKERRQ(PetscSynchronizedFlush(comm, NULL));
8820068a5610SStefano Zampini 
8821068a5610SStefano Zampini   if (size > 1) {
8822068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8823068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8824068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8825068a5610SStefano Zampini     MPI_Op        statReduce;
8826068a5610SStefano Zampini 
88275f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType));
88285f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_commit(&statType));
88295f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
88305f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm));
88315f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Op_free(&statReduce));
88325f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_free(&statType));
8833068a5610SStefano Zampini   } else {
88345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(&globalStats,&stats,1));
8835068a5610SStefano Zampini   }
8836dd400576SPatrick Sanan   if (rank == 0) {
8837068a5610SStefano Zampini     count = globalStats.count;
8838068a5610SStefano Zampini     min   = globalStats.min;
8839068a5610SStefano Zampini     max   = globalStats.max;
8840068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8841068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8842068a5610SStefano Zampini   }
8843068a5610SStefano Zampini 
8844068a5610SStefano Zampini   if (output) {
88455f80ce2aSJacob Faibussowitsch     CHKERRQ(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));
8846068a5610SStefano Zampini   }
88475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(J,invJ));
8848068a5610SStefano Zampini 
88495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoarseDM(dm,&dmCoarse));
8850068a5610SStefano Zampini   if (dmCoarse) {
8851068a5610SStefano Zampini     PetscBool isplex;
8852068a5610SStefano Zampini 
88535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex));
8854068a5610SStefano Zampini     if (isplex) {
88555f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexCheckCellShape(dmCoarse,output,condLimit));
8856068a5610SStefano Zampini     }
8857068a5610SStefano Zampini   }
8858068a5610SStefano Zampini   PetscFunctionReturn(0);
8859068a5610SStefano Zampini }
8860068a5610SStefano Zampini 
8861f108dbd7SJacob Faibussowitsch /*@
8862f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8863f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8864f108dbd7SJacob Faibussowitsch 
88656ed19f2fSJacob Faibussowitsch   Collective on dm
8866f108dbd7SJacob Faibussowitsch 
8867f108dbd7SJacob Faibussowitsch   Input Parameters:
8868f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8869f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8870f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8871f108dbd7SJacob Faibussowitsch 
8872f108dbd7SJacob Faibussowitsch   Output Parameters:
8873f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8874f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8875f108dbd7SJacob Faibussowitsch 
8876f108dbd7SJacob Faibussowitsch   Options Database Keys:
8877f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8878f108dbd7SJacob Faibussowitsch supported.
8879f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8880f108dbd7SJacob Faibussowitsch 
8881f108dbd7SJacob Faibussowitsch   Notes:
8882f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8883f108dbd7SJacob Faibussowitsch 
8884f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8885f108dbd7SJacob Faibussowitsch 
8886f108dbd7SJacob 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
8887f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8888f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8889f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8890f108dbd7SJacob Faibussowitsch 
8891f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8892f108dbd7SJacob Faibussowitsch 
8893f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8894f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8895f108dbd7SJacob Faibussowitsch 
8896f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8897f108dbd7SJacob Faibussowitsch 
8898f108dbd7SJacob Faibussowitsch   Level: intermediate
8899f108dbd7SJacob Faibussowitsch 
8900f108dbd7SJacob Faibussowitsch .seealso: DMPlexCheckCellShape(), DMCreateLabel()
8901f108dbd7SJacob Faibussowitsch @*/
8902f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
8903f108dbd7SJacob Faibussowitsch {
89046ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
89056ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
89066ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
8907f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
89086ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
8909f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
8910f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
8911f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
8912f108dbd7SJacob Faibussowitsch   IS                      glob;
8913f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
8914f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
8915f108dbd7SJacob Faibussowitsch 
8916f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8917f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89186ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
8919f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
89206bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
89215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) dm, &comm));
89225f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDimension(dm, &nc));
89232c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc);
89246ed19f2fSJacob Faibussowitsch   {
89256ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
89266ed19f2fSJacob Faibussowitsch 
89275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexIsInterpolated(dm, &interpFlag));
8928f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
8929f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
8930f108dbd7SJacob Faibussowitsch 
89315f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Comm_rank(comm, &rank));
893298921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
8933f108dbd7SJacob Faibussowitsch     }
89346ed19f2fSJacob Faibussowitsch   }
8935f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
8936f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
89375f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateLabel(dm, "Orthogonal_Quality"));
89385f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
89396ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
89405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetVTKCellHeight(dm, &cellHeight));
89415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
89425f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
89435f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(glob, &ltog));
89445f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
89455f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(comm, OrthQual));
89465f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(*OrthQual, VECSTANDARD));
89475f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE));
89485f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetLocalToGlobalMapping(*OrthQual, ltog));
89495f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetUp(*OrthQual));
89505f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&glob));
89515f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&ltog));
89525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
89535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(cellgeom, &cellGeomArr));
89545f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(facegeom, &faceGeomArr));
89555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(cellgeom, &dmCell));
89565f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(facegeom, &dmFace));
89575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
89586ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
89596ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
8960f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
8961f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
8962898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
8963f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
8964f108dbd7SJacob Faibussowitsch 
89656ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
8966f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
8967f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
89685f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
89695f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
8970f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
89715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
89726ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
89736ed19f2fSJacob Faibussowitsch       PetscInt         i;
89746ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
8975f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
8976f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
8977f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
8978f108dbd7SJacob Faibussowitsch 
8979f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
8980f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
89815f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
8982f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
89836ed19f2fSJacob Faibussowitsch       {
89846ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
89856ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
89866ed19f2fSJacob Faibussowitsch 
89875f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
89885f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
89895f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
89906ed19f2fSJacob Faibussowitsch       }
8991f108dbd7SJacob Faibussowitsch 
8992f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
8993f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
8994f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
8995f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
8996f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
8997addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
8998addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
8999addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9000f108dbd7SJacob Faibussowitsch       }
9001addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9002addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9003addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9004f108dbd7SJacob Faibussowitsch 
9005f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9006f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9007f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
9008f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
9009f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
9010f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9011f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
9012f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
9013f108dbd7SJacob Faibussowitsch       }
9014f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
9015f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
9016f108dbd7SJacob Faibussowitsch       }
9017f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
9018f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
9019f108dbd7SJacob Faibussowitsch       }
9020f108dbd7SJacob Faibussowitsch     }
90215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(adj));
90225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(cArr, fArr));
9023f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
90246ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9025f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
90265f80ce2aSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) CHKERRQ(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9027f108dbd7SJacob Faibussowitsch     }
9028f108dbd7SJacob Faibussowitsch   }
90295f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES));
90305f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyBegin(*OrthQual));
90315f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyEnd(*OrthQual));
90325f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(cellgeom, &cellGeomArr));
90335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(facegeom, &faceGeomArr));
90345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9035f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
90365f80ce2aSJacob Faibussowitsch     if (vwr) CHKERRQ(DMLabelView(*OrthQualLabel, vwr));
9037f108dbd7SJacob Faibussowitsch   }
90385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree5(idx, oqVals, ci, fi, Ai));
90395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDestroy(&vwr));
90405f80ce2aSJacob Faibussowitsch   CHKERRQ(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9041f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9042f108dbd7SJacob Faibussowitsch }
9043f108dbd7SJacob Faibussowitsch 
90441eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
90451eb70e55SToby Isaac  * interpolator construction */
90461eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
90471eb70e55SToby Isaac {
90481eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
90491eb70e55SToby Isaac   PetscSF        sf;
90501eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
90511eb70e55SToby Isaac 
90521eb70e55SToby Isaac   PetscFunctionBegin;
90531eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
90541eb70e55SToby Isaac   PetscValidPointer(odm,2);
90555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(dm, &section));
90565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionHasConstraints(section, &hasConstraints));
90575f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm)));
90581eb70e55SToby Isaac   if (!ghasConstraints) {
90595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)dm));
90601eb70e55SToby Isaac     *odm = dm;
90611eb70e55SToby Isaac     PetscFunctionReturn(0);
90621eb70e55SToby Isaac   }
90635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMClone(dm, odm));
90645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyFields(dm, *odm));
90655f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(*odm, &newSection));
90665f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetPointSF(*odm, &sf));
90675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
90685f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetGlobalSection(*odm, gsection));
90695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&gsection));
90701eb70e55SToby Isaac   PetscFunctionReturn(0);
90711eb70e55SToby Isaac }
90721eb70e55SToby Isaac 
90731eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
90741eb70e55SToby Isaac {
90751eb70e55SToby Isaac   DM             dmco, dmfo;
90761eb70e55SToby Isaac   Mat            interpo;
90771eb70e55SToby Isaac   Vec            rscale;
90781eb70e55SToby Isaac   Vec            cglobalo, clocal;
90791eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
90801eb70e55SToby Isaac   PetscBool      regular;
90811eb70e55SToby Isaac 
90821eb70e55SToby Isaac   PetscFunctionBegin;
90835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetFullDM(dmc, &dmco));
90845f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetFullDM(dmf, &dmfo));
90855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoarseDM(dmfo, dmco));
90865f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetRegularRefinement(dmf, &regular));
90875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetRegularRefinement(dmfo, regular));
90885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
90895f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(dmco, &cglobalo));
90905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLocalVector(dmc, &clocal));
90915f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(cglobalo, 0.));
90925f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(clocal, 0.));
90935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(dmf, &fglobal));
90945f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(dmfo, &fglobalo));
90955f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLocalVector(dmf, &flocal));
90965f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(fglobal, 0.));
90975f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(fglobalo, 0.));
90985f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(flocal, 0.));
90995f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
91005f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
91015f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
91025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMult(interpo, cglobalo, fglobalo));
91035f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
91045f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
91055f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
91065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
91071eb70e55SToby Isaac   *shift = fglobal;
91085f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&flocal));
91095f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&fglobalo));
91105f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&clocal));
91115f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&cglobalo));
91125f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&rscale));
91135f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&interpo));
91145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&dmfo));
91155f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&dmco));
91161eb70e55SToby Isaac   PetscFunctionReturn(0);
91171eb70e55SToby Isaac }
91181eb70e55SToby Isaac 
91191eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
91201eb70e55SToby Isaac {
91211eb70e55SToby Isaac   PetscObject    shifto;
91221eb70e55SToby Isaac   Vec            shift;
91231eb70e55SToby Isaac 
91241eb70e55SToby Isaac   PetscFunctionBegin;
91251eb70e55SToby Isaac   if (!interp) {
91261eb70e55SToby Isaac     Vec rscale;
91271eb70e55SToby Isaac 
91285f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateInterpolation(coarse, fine, &interp, &rscale));
91295f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&rscale));
91301eb70e55SToby Isaac   } else {
91315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)interp));
91321eb70e55SToby Isaac   }
91335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
91341eb70e55SToby Isaac   if (!shifto) {
91355f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
91365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift));
91371eb70e55SToby Isaac     shifto = (PetscObject) shift;
91385f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&shift));
91391eb70e55SToby Isaac   }
91401eb70e55SToby Isaac   shift = (Vec) shifto;
91415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatInterpolate(interp, coarseSol, fineSol));
91425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAXPY(fineSol, 1.0, shift));
91435f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&interp));
91441eb70e55SToby Isaac   PetscFunctionReturn(0);
91451eb70e55SToby Isaac }
91461eb70e55SToby Isaac 
9147bceba477SMatthew G. Knepley /* Pointwise interpolation
9148bceba477SMatthew G. Knepley      Just code FEM for now
9149bceba477SMatthew G. Knepley      u^f = I u^c
91504ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
91514ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
91524ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9153bceba477SMatthew G. Knepley */
9154bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9155bceba477SMatthew G. Knepley {
9156bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
9157bceba477SMatthew G. Knepley   PetscInt       m, n;
9158a063dac3SMatthew G. Knepley   void          *ctx;
915968132eb9SMatthew G. Knepley   DM             cdm;
9160cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9161bceba477SMatthew G. Knepley 
9162bceba477SMatthew G. Knepley   PetscFunctionBegin;
91635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalSection(dmFine, &gsf));
91645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetConstrainedStorageSize(gsf, &m));
91655f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalSection(dmCoarse, &gsc));
91665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetConstrainedStorageSize(gsc, &n));
916768132eb9SMatthew G. Knepley 
91685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
91695f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation));
91705f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
91715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
91725f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetApplicationContext(dmFine, &ctx));
917368132eb9SMatthew G. Knepley 
91745f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoarseDM(dmFine, &cdm));
91755f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetRegularRefinement(dmFine, &regular));
91765f80ce2aSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) CHKERRQ(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
91775f80ce2aSJacob Faibussowitsch   else                                            CHKERRQ(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
91785f80ce2aSJacob Faibussowitsch   CHKERRQ(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
91794db47ee9SStefano Zampini   if (scaling) {
91805d1c2e58SMatthew G. Knepley     /* Use naive scaling */
91815f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
91824db47ee9SStefano Zampini   }
9183a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9184a063dac3SMatthew G. Knepley }
9185bceba477SMatthew G. Knepley 
91866dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9187a063dac3SMatthew G. Knepley {
91886dbf9973SLawrence Mitchell   VecScatter     ctx;
918990748bafSMatthew G. Knepley 
9190a063dac3SMatthew G. Knepley   PetscFunctionBegin;
91915f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
91925f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
91935f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&ctx));
9194bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9195bceba477SMatthew G. Knepley }
9196bceba477SMatthew G. Knepley 
91973e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
91983e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
91993e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
92003e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
92013e9753d6SMatthew G. Knepley {
920200635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
920300635df3SMatthew G. Knepley   PetscInt       c;
920400635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
92053e9753d6SMatthew G. Knepley }
92063e9753d6SMatthew G. Knepley 
9207b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9208b4937a87SMatthew G. Knepley {
9209b4937a87SMatthew G. Knepley   DM             dmc;
9210b4937a87SMatthew G. Knepley   PetscDS        ds;
9211b4937a87SMatthew G. Knepley   Vec            ones, locmass;
9212b4937a87SMatthew G. Knepley   IS             cellIS;
9213b4937a87SMatthew G. Knepley   PetscFormKey   key;
9214b4937a87SMatthew G. Knepley   PetscInt       depth;
9215b4937a87SMatthew G. Knepley 
9216b4937a87SMatthew G. Knepley   PetscFunctionBegin;
92175f80ce2aSJacob Faibussowitsch   CHKERRQ(DMClone(dm, &dmc));
92185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyDisc(dm, dmc));
92195f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetDS(dmc, &ds));
92205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92215f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(dmc, mass));
92225f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalVector(dmc, &ones));
92235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalVector(dmc, &locmass));
92245f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetDepth(dmc, &depth));
92255f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92265f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(locmass, 0.0));
92275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(ones, 1.0));
9228b4937a87SMatthew G. Knepley   key.label = NULL;
9229b4937a87SMatthew G. Knepley   key.value = 0;
9230b4937a87SMatthew G. Knepley   key.field = 0;
9231b4937a87SMatthew G. Knepley   key.part  = 0;
92325f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
92335f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&cellIS));
92345f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(*mass, 0.0));
92355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
92365f80ce2aSJacob Faibussowitsch   CHKERRQ(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
92375f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreLocalVector(dmc, &ones));
92385f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreLocalVector(dmc, &locmass));
92395f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&dmc));
9240b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9241b4937a87SMatthew G. Knepley }
9242b4937a87SMatthew G. Knepley 
9243bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9244bd041c0cSMatthew G. Knepley {
9245bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
9246bd041c0cSMatthew G. Knepley   PetscInt       m, n;
9247bd041c0cSMatthew G. Knepley   void          *ctx;
9248bd041c0cSMatthew G. Knepley   DM             cdm;
9249bd041c0cSMatthew G. Knepley   PetscBool      regular;
9250bd041c0cSMatthew G. Knepley 
9251bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
92523e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
92533e9753d6SMatthew G. Knepley     DM            dmc;
92543e9753d6SMatthew G. Knepley     PetscDS       ds;
9255b4937a87SMatthew G. Knepley     PetscWeakForm wf;
92563e9753d6SMatthew G. Knepley     Vec           u;
92573e9753d6SMatthew G. Knepley     IS            cellIS;
925806ad1575SMatthew G. Knepley     PetscFormKey  key;
92593e9753d6SMatthew G. Knepley     PetscInt      depth;
92603e9753d6SMatthew G. Knepley 
92615f80ce2aSJacob Faibussowitsch     CHKERRQ(DMClone(dmFine, &dmc));
92625f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCopyDisc(dmFine, dmc));
92635f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDS(dmc, &ds));
92645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDSGetWeakForm(ds, &wf));
92655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscWeakFormClear(wf));
92665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92675f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateMatrix(dmc, mass));
92685f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalVector(dmc, &u));
92695f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepth(dmc, &depth));
92705f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92715f80ce2aSJacob Faibussowitsch     CHKERRQ(MatZeroEntries(*mass));
92726528b96dSMatthew G. Knepley     key.label = NULL;
92736528b96dSMatthew G. Knepley     key.value = 0;
92746528b96dSMatthew G. Knepley     key.field = 0;
927506ad1575SMatthew G. Knepley     key.part  = 0;
92765f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
92775f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&cellIS));
92785f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreGlobalVector(dmc, &u));
92795f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(&dmc));
92803e9753d6SMatthew G. Knepley   } else {
92815f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(dmFine, &gsf));
92825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetConstrainedStorageSize(gsf, &m));
92835f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(dmCoarse, &gsc));
92845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetConstrainedStorageSize(gsc, &n));
9285bd041c0cSMatthew G. Knepley 
92865f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass));
92875f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
92885f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(*mass, dmCoarse->mattype));
92895f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetApplicationContext(dmFine, &ctx));
9290bd041c0cSMatthew G. Knepley 
92915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoarseDM(dmFine, &cdm));
92925f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetRegularRefinement(dmFine, &regular));
92935f80ce2aSJacob Faibussowitsch     if (regular && cdm == dmCoarse) CHKERRQ(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
92945f80ce2aSJacob Faibussowitsch     else                            CHKERRQ(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
92953e9753d6SMatthew G. Knepley   }
92965f80ce2aSJacob Faibussowitsch   CHKERRQ(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9297bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9298bd041c0cSMatthew G. Knepley }
9299bd041c0cSMatthew G. Knepley 
93000aef6b92SMatthew G. Knepley /*@
93010aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93020aef6b92SMatthew G. Knepley 
93030aef6b92SMatthew G. Knepley   Input Parameter:
93040aef6b92SMatthew G. Knepley . dm - The DMPlex object
93050aef6b92SMatthew G. Knepley 
93060aef6b92SMatthew G. Knepley   Output Parameter:
93070aef6b92SMatthew G. Knepley . regular - The flag
93080aef6b92SMatthew G. Knepley 
93090aef6b92SMatthew G. Knepley   Level: intermediate
93100aef6b92SMatthew G. Knepley 
93110aef6b92SMatthew G. Knepley .seealso: DMPlexSetRegularRefinement()
93120aef6b92SMatthew G. Knepley @*/
93130aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
93140aef6b92SMatthew G. Knepley {
93150aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93160aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9317*dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
93180aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
93190aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93200aef6b92SMatthew G. Knepley }
93210aef6b92SMatthew G. Knepley 
93220aef6b92SMatthew G. Knepley /*@
93230aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93240aef6b92SMatthew G. Knepley 
93250aef6b92SMatthew G. Knepley   Input Parameters:
93260aef6b92SMatthew G. Knepley + dm - The DMPlex object
93270aef6b92SMatthew G. Knepley - regular - The flag
93280aef6b92SMatthew G. Knepley 
93290aef6b92SMatthew G. Knepley   Level: intermediate
93300aef6b92SMatthew G. Knepley 
93310aef6b92SMatthew G. Knepley .seealso: DMPlexGetRegularRefinement()
93320aef6b92SMatthew G. Knepley @*/
93330aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
93340aef6b92SMatthew G. Knepley {
93350aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93360aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93370aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
93380aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93390aef6b92SMatthew G. Knepley }
93400aef6b92SMatthew G. Knepley 
9341f7c74593SToby Isaac /* anchors */
9342a68b90caSToby Isaac /*@
9343f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9344ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9345a68b90caSToby Isaac 
9346e228b242SToby Isaac   not collective
9347a68b90caSToby Isaac 
9348f899ff85SJose E. Roman   Input Parameter:
9349a68b90caSToby Isaac . dm - The DMPlex object
9350a68b90caSToby Isaac 
9351a68b90caSToby Isaac   Output Parameters:
9352a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9353a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9354a68b90caSToby Isaac 
9355a68b90caSToby Isaac   Level: intermediate
9356a68b90caSToby Isaac 
9357ebdb1bfaSJed Brown .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints()
9358a68b90caSToby Isaac @*/
9359a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9360a68b90caSToby Isaac {
9361a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9362a68b90caSToby Isaac 
9363a68b90caSToby Isaac   PetscFunctionBegin;
9364a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93655f80ce2aSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) CHKERRQ((*plex->createanchors)(dm));
9366a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9367a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9368a68b90caSToby Isaac   PetscFunctionReturn(0);
9369a68b90caSToby Isaac }
9370a68b90caSToby Isaac 
9371a68b90caSToby Isaac /*@
9372f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9373f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9374a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9375a68b90caSToby Isaac 
9376a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9377ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9378a68b90caSToby Isaac 
9379e228b242SToby Isaac   collective on dm
9380a68b90caSToby Isaac 
9381a68b90caSToby Isaac   Input Parameters:
9382a68b90caSToby Isaac + dm - The DMPlex object
9383e228b242SToby 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).
9384e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9385a68b90caSToby Isaac 
9386a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9387a68b90caSToby Isaac 
9388a68b90caSToby Isaac   Level: intermediate
9389a68b90caSToby Isaac 
9390ebdb1bfaSJed Brown .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints()
9391a68b90caSToby Isaac @*/
9392a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9393a68b90caSToby Isaac {
9394a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9395e228b242SToby Isaac   PetscMPIInt    result;
9396a68b90caSToby Isaac 
9397a68b90caSToby Isaac   PetscFunctionBegin;
9398a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9399e228b242SToby Isaac   if (anchorSection) {
9400e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
94015f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result));
94022c71b3e2SJacob Faibussowitsch     PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9403e228b242SToby Isaac   }
9404e228b242SToby Isaac   if (anchorIS) {
9405e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
94065f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result));
94072c71b3e2SJacob Faibussowitsch     PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9408e228b242SToby Isaac   }
9409a68b90caSToby Isaac 
94105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)anchorSection));
94115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&plex->anchorSection));
9412a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9413a68b90caSToby Isaac 
94145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)anchorIS));
94155f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&plex->anchorIS));
9416a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9417a68b90caSToby Isaac 
9418cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9419a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9420a68b90caSToby Isaac     const PetscInt *anchors;
9421a68b90caSToby Isaac 
94225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
94235f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(anchorIS,&size));
94245f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(anchorIS,&anchors));
9425a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9426a68b90caSToby Isaac       PetscInt p;
9427a68b90caSToby Isaac 
9428a68b90caSToby Isaac       p = anchors[a];
9429a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9430a68b90caSToby Isaac         PetscInt dof;
9431a68b90caSToby Isaac 
94325f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(anchorSection,p,&dof));
9433a68b90caSToby Isaac         if (dof) {
9434a68b90caSToby Isaac 
94355f80ce2aSJacob Faibussowitsch           CHKERRQ(ISRestoreIndices(anchorIS,&anchors));
943698921bdaSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p);
9437a68b90caSToby Isaac         }
9438a68b90caSToby Isaac       }
9439a68b90caSToby Isaac     }
94405f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(anchorIS,&anchors));
9441a68b90caSToby Isaac   }
9442f7c74593SToby Isaac   /* reset the generic constraints */
94435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetDefaultConstraints(dm,NULL,NULL,NULL));
9444a68b90caSToby Isaac   PetscFunctionReturn(0);
9445a68b90caSToby Isaac }
9446a68b90caSToby Isaac 
9447f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9448a68b90caSToby Isaac {
9449f7c74593SToby Isaac   PetscSection anchorSection;
94506995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9451a68b90caSToby Isaac 
9452a68b90caSToby Isaac   PetscFunctionBegin;
9453a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94545f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetAnchors(dm,&anchorSection,NULL));
94555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(PETSC_COMM_SELF,cSec));
94565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section,&numFields));
94576995de1eSToby Isaac   if (numFields) {
9458719ab38cSToby Isaac     PetscInt f;
94595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetNumFields(*cSec,numFields));
9460719ab38cSToby Isaac 
9461719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9462719ab38cSToby Isaac       PetscInt numComp;
9463719ab38cSToby Isaac 
94645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetFieldComponents(section,f,&numComp));
94655f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetFieldComponents(*cSec,f,numComp));
9466719ab38cSToby Isaac     }
94676995de1eSToby Isaac   }
94685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
94695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(section,&sStart,&sEnd));
94706995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
94716995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
94726995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
94735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(*cSec,pStart,pEnd));
9474a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
94755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(anchorSection,p,&dof));
9476a68b90caSToby Isaac     if (dof) {
94775f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(section,p,&dof));
94785f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionSetDof(*cSec,p,dof));
9479a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
94805f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetFieldDof(section,p,f,&dof));
94815f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionSetFieldDof(*cSec,p,f,dof));
9482a68b90caSToby Isaac       }
9483a68b90caSToby Isaac     }
9484a68b90caSToby Isaac   }
94855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(*cSec));
94865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *cSec, "Constraint Section"));
9487a68b90caSToby Isaac   PetscFunctionReturn(0);
9488a68b90caSToby Isaac }
9489a68b90caSToby Isaac 
9490f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9491a68b90caSToby Isaac {
9492f7c74593SToby Isaac   PetscSection   aSec;
9493ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
94940ac89760SToby Isaac   const PetscInt *anchors;
94950ac89760SToby Isaac   PetscInt       numFields, f;
949666ad2231SToby Isaac   IS             aIS;
9497e19f7ee6SMark Adams   MatType        mtype;
9498e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
94990ac89760SToby Isaac 
95000ac89760SToby Isaac   PetscFunctionBegin;
95010ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(cSec, &m));
95035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(section, &n));
95045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_SELF,cMat));
95055f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*cMat,m,n,m,n));
95065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda));
95075f80ce2aSJacob Faibussowitsch   if (!iscuda) CHKERRQ(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda));
95085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos));
95095f80ce2aSJacob Faibussowitsch   if (!iskokkos) CHKERRQ(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos));
9510e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9511e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9512e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
95135f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*cMat,mtype));
95145f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetAnchors(dm,&aSec,&aIS));
95155f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(aIS,&anchors));
95166995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
95175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(cSec,&pStart,&pEnd));
95185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetChart(section,&sStart,&sEnd));
95195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m+1,&i));
95200ac89760SToby Isaac   i[0] = 0;
95215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetNumFields(section,&numFields));
95220ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9523f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9524f19733c5SToby Isaac 
95255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetDof(aSec,p,&rDof));
9526f19733c5SToby Isaac     if (!rDof) continue;
95275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetOffset(aSec,p,&rOff));
95280ac89760SToby Isaac     if (numFields) {
95290ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95300ac89760SToby Isaac         annz = 0;
9531f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9532f19733c5SToby Isaac           a = anchors[rOff + r];
9533ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95345f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(section,a,f,&aDof));
95350ac89760SToby Isaac           annz += aDof;
95360ac89760SToby Isaac         }
95375f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&dof));
95385f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetFieldOffset(cSec,p,f,&off));
95390ac89760SToby Isaac         for (q = 0; q < dof; q++) {
95400ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
95410ac89760SToby Isaac         }
95420ac89760SToby Isaac       }
95432f7452b8SBarry Smith     } else {
95440ac89760SToby Isaac       annz = 0;
95455f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(cSec,p,&dof));
95460ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9547ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9548ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
95495f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(section,a,&aDof));
95500ac89760SToby Isaac         annz += aDof;
95510ac89760SToby Isaac       }
95525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(cSec,p,&dof));
95535f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetOffset(cSec,p,&off));
95540ac89760SToby Isaac       for (q = 0; q < dof; q++) {
95550ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
95560ac89760SToby Isaac       }
95570ac89760SToby Isaac     }
95580ac89760SToby Isaac   }
95590ac89760SToby Isaac   nnz = i[m];
95605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nnz,&j));
95610ac89760SToby Isaac   offset = 0;
95620ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
95630ac89760SToby Isaac     if (numFields) {
95640ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95655f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetFieldDof(cSec,p,f,&dof));
95660ac89760SToby Isaac         for (q = 0; q < dof; q++) {
95670ac89760SToby Isaac           PetscInt rDof, rOff, r;
95685f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetDof(aSec,p,&rDof));
95695f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetOffset(aSec,p,&rOff));
95700ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
95710ac89760SToby Isaac             PetscInt s;
95720ac89760SToby Isaac 
95730ac89760SToby Isaac             a = anchors[rOff + r];
9574ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
95755f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldDof(section,a,f,&aDof));
95765f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldOffset(section,a,f,&aOff));
95770ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
95780ac89760SToby Isaac               j[offset++] = aOff + s;
95790ac89760SToby Isaac             }
95800ac89760SToby Isaac           }
95810ac89760SToby Isaac         }
95820ac89760SToby Isaac       }
95832f7452b8SBarry Smith     } else {
95845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(cSec,p,&dof));
95850ac89760SToby Isaac       for (q = 0; q < dof; q++) {
95860ac89760SToby Isaac         PetscInt rDof, rOff, r;
95875f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(aSec,p,&rDof));
95885f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(aSec,p,&rOff));
95890ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
95900ac89760SToby Isaac           PetscInt s;
95910ac89760SToby Isaac 
95920ac89760SToby Isaac           a = anchors[rOff + r];
9593ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95945f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetDof(section,a,&aDof));
95955f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetOffset(section,a,&aOff));
95960ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
95970ac89760SToby Isaac             j[offset++] = aOff + s;
95980ac89760SToby Isaac           }
95990ac89760SToby Isaac         }
96000ac89760SToby Isaac       }
96010ac89760SToby Isaac     }
96020ac89760SToby Isaac   }
96035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL));
96045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(i));
96055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(j));
96065f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(aIS,&anchors));
96070ac89760SToby Isaac   PetscFunctionReturn(0);
96080ac89760SToby Isaac }
96090ac89760SToby Isaac 
961066ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
961166ad2231SToby Isaac {
9612f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9613f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
961466ad2231SToby Isaac   Mat            cMat;
961566ad2231SToby Isaac 
961666ad2231SToby Isaac   PetscFunctionBegin;
961766ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetAnchors(dm,&anchorSection,NULL));
961966ad2231SToby Isaac   if (anchorSection) {
962044a7f3ddSMatthew G. Knepley     PetscInt Nf;
9621e228b242SToby Isaac 
96225f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLocalSection(dm,&section));
96235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec));
96245f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat));
96255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetNumFields(dm,&Nf));
96265f80ce2aSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) CHKERRQ((*plex->computeanchormatrix)(dm,section,cSec,cMat));
96275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetDefaultConstraints(dm,cSec,cMat,NULL));
96285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionDestroy(&cSec));
96295f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&cMat));
963066ad2231SToby Isaac   }
963166ad2231SToby Isaac   PetscFunctionReturn(0);
963266ad2231SToby Isaac }
9633a93c429eSMatthew G. Knepley 
9634a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9635a93c429eSMatthew G. Knepley {
9636a93c429eSMatthew G. Knepley   IS             subis;
9637a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9638a93c429eSMatthew G. Knepley 
9639a93c429eSMatthew G. Knepley   PetscFunctionBegin;
96405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetLocalSection(dm, &section));
964128b400f6SJacob Faibussowitsch   PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
964228b400f6SJacob Faibussowitsch   PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9643a93c429eSMatthew G. Knepley   /* Create subdomain */
96445f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexFilter(dm, label, value, subdm));
9645a93c429eSMatthew G. Knepley   /* Create submodel */
96465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetSubpointIS(*subdm, &subis));
96475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreateSubmeshSection(section, subis, &subsection));
96485f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetLocalSection(*subdm, subsection));
96495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&subsection));
96505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCopyDisc(dm, *subdm));
9651a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9652a93c429eSMatthew G. Knepley   if (is) {
9653a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9654a93c429eSMatthew G. Knepley     IS              spIS;
9655a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9656a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9657a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9658a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9659a93c429eSMatthew G. Knepley 
96605f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetSubpointIS(*subdm, &spIS));
96615f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(spIS, &spmap));
96625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetNumFields(section, &Nf));
96635f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(dm, &sectionGlobal));
96645f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalSection(*subdm, &subsectionGlobal));
96655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionGetChart(subsection, &pStart, &pEnd));
9666a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9667a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9668a93c429eSMatthew G. Knepley 
96695f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(sectionGlobal, p, &gdof));
9670a93c429eSMatthew G. Knepley       if (gdof > 0) {
9671a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9672a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9673a93c429eSMatthew G. Knepley 
96745f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(subsection, p, f, &fdof));
96755f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
9676a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9677a93c429eSMatthew G. Knepley         }
9678a93c429eSMatthew G. Knepley         subSize += pSubSize;
9679a93c429eSMatthew G. Knepley         if (pSubSize) {
9680a93c429eSMatthew G. Knepley           if (bs < 0) {
9681a93c429eSMatthew G. Knepley             bs = pSubSize;
9682a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9683a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9684a93c429eSMatthew G. Knepley             bs = 1;
9685a93c429eSMatthew G. Knepley           }
9686a93c429eSMatthew G. Knepley         }
9687a93c429eSMatthew G. Knepley       }
9688a93c429eSMatthew G. Knepley     }
9689a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9690a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
96915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
9692a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9693a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
96945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(subSize, &subIndices));
9695a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9696a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9697a93c429eSMatthew G. Knepley 
96985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSectionGetDof(subsectionGlobal, p, &gdof));
9699a93c429eSMatthew G. Knepley       if (gdof > 0) {
9700a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9701a93c429eSMatthew G. Knepley 
97025f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetOffset(sectionGlobal, point, &goff));
9703a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9704a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9705a93c429eSMatthew G. Knepley 
9706a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9707a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
97085f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldDof(section, p, f2, &fdof));
97095f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
9710a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9711a93c429eSMatthew G. Knepley           }
97125f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldDof(section, p, f, &fdof));
97135f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
9714a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9715a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9716a93c429eSMatthew G. Knepley           }
9717a93c429eSMatthew G. Knepley         }
9718a93c429eSMatthew G. Knepley       }
9719a93c429eSMatthew G. Knepley     }
97205f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(spIS, &spmap));
97215f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
9722a93c429eSMatthew G. Knepley     if (bs > 1) {
9723a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9724a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9725a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9726a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9727a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9728a93c429eSMatthew G. Knepley         }
9729a93c429eSMatthew G. Knepley       }
97305f80ce2aSJacob Faibussowitsch       if (set) CHKERRQ(ISSetBlockSize(*is, bs));
9731a93c429eSMatthew G. Knepley     }
9732a93c429eSMatthew G. Knepley     /* Attach nullspace */
9733a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9734a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9735a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9736a93c429eSMatthew G. Knepley     }
9737a93c429eSMatthew G. Knepley     if (f < Nf) {
9738a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
97395f80ce2aSJacob Faibussowitsch       CHKERRQ((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
97406823f3c5SBlaise Bourdin 
97415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace));
97425f80ce2aSJacob Faibussowitsch       CHKERRQ(MatNullSpaceDestroy(&nullSpace));
9743a93c429eSMatthew G. Knepley     }
9744a93c429eSMatthew G. Knepley   }
9745a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9746a93c429eSMatthew G. Knepley }
9747c0f0dcc3SMatthew G. Knepley 
9748c0f0dcc3SMatthew G. Knepley /*@
9749c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9750c0f0dcc3SMatthew G. Knepley 
9751c0f0dcc3SMatthew G. Knepley   Input Parameter:
9752c0f0dcc3SMatthew G. Knepley - dm - The DM
9753c0f0dcc3SMatthew G. Knepley 
9754c0f0dcc3SMatthew G. Knepley   Level: developer
9755c0f0dcc3SMatthew G. Knepley 
9756c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9757c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9758c0f0dcc3SMatthew G. Knepley 
9759c0f0dcc3SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreate()
9760c0f0dcc3SMatthew G. Knepley @*/
9761c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9762c0f0dcc3SMatthew G. Knepley {
9763e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9764c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9765c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9766c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9767c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9768c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9769c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9770c0f0dcc3SMatthew G. Knepley   const char        *name;
9771e5ed2c37SJose E. Roman #endif
9772c0f0dcc3SMatthew G. Knepley 
9773c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9774c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9775c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
97765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) dm, &name));
97775f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
97785f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetNumFields(dm, &Nf));
97795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogGetStageLog(&stageLog));
97805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStageLogGetCurrent(stageLog, &stage));
97815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventGetId("DMPlexResidualFE", &event));
97825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
9783c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9784c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9785c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
97865f80ce2aSJacob Faibussowitsch   CHKERRQ(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)));
9787c0f0dcc3SMatthew G. Knepley #else
9788c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9789c0f0dcc3SMatthew G. Knepley #endif
9790c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9791c0f0dcc3SMatthew G. Knepley }
9792