xref: /petsc/src/dm/impls/plex/plex.c (revision c306944f08e690230c054264854657fa15a316fe)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h>
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
60c312b8eSJed Brown #include <petscsf.h>
7e228b242SToby Isaac #include <petscds.h>
8e412dcbdSMatthew G. Knepley #include <petscdraw.h>
9f19dbd58SToby Isaac #include <petscdmfield.h>
10012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
11552f7358SJed Brown 
12552f7358SJed Brown /* Logging support */
1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad;
14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate;
15552f7358SJed Brown 
16f39ec787SMatthew G. Knepley PetscBool  Plexcite       = PETSC_FALSE;
17f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n"
18f39ec787SMatthew G. Knepley                             "title     = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n"
19f39ec787SMatthew G. Knepley                             "author    = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n"
20f39ec787SMatthew G. Knepley                             "journal   = {SIAM Journal on Scientific Computing},\n"
21f39ec787SMatthew G. Knepley                             "volume    = {38},\n"
22f39ec787SMatthew G. Knepley                             "number    = {5},\n"
23f39ec787SMatthew G. Knepley                             "pages     = {S143--S155},\n"
24f39ec787SMatthew G. Knepley                             "eprint    = {http://arxiv.org/abs/1506.07749},\n"
25f39ec787SMatthew G. Knepley                             "doi       = {10.1137/15M1026092},\n"
26f39ec787SMatthew G. Knepley                             "year      = {2016},\n"
27f39ec787SMatthew G. Knepley                             "petsc_uses={DMPlex},\n}\n";
28f39ec787SMatthew G. Knepley 
295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
30552f7358SJed Brown 
31e5337592SStefano Zampini /*@
329318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
339318fe57SMatthew G. Knepley 
349318fe57SMatthew G. Knepley   Input Parameter:
35a1cb98faSBarry Smith . dm - The `DMPLEX` object
369318fe57SMatthew G. Knepley 
379318fe57SMatthew G. Knepley   Output Parameter:
389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
399318fe57SMatthew G. Knepley 
409318fe57SMatthew G. Knepley   Level: intermediate
419318fe57SMatthew G. Knepley 
42a1cb98faSBarry Smith   Note:
43a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
44a1cb98faSBarry Smith   If the mesh has no cells, this returns `PETSC_FALSE`.
45a1cb98faSBarry Smith 
461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
479318fe57SMatthew G. Knepley @*/
48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
49d71ae5a4SJacob Faibussowitsch {
509318fe57SMatthew G. Knepley   DMPolytopeType ct;
519318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
529318fe57SMatthew G. Knepley 
539318fe57SMatthew G. Knepley   PetscFunctionBegin;
549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
559371c9d4SSatish Balay   if (cEnd <= cStart) {
569371c9d4SSatish Balay     *simplex = PETSC_FALSE;
573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
589371c9d4SSatish Balay   }
599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
609318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629318fe57SMatthew G. Knepley }
639318fe57SMatthew G. Knepley 
649318fe57SMatthew G. Knepley /*@
65412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
66e5337592SStefano Zampini 
67d8d19677SJose E. Roman   Input Parameters:
68a1cb98faSBarry Smith + dm     - The `DMPLEX` object
69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
70e5337592SStefano Zampini 
71e5337592SStefano Zampini   Output Parameters:
72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
7340196513SBarry Smith - cEnd   - The upper bound on "normal" cells
74e5337592SStefano Zampini 
75412e9a14SMatthew G. Knepley   Level: developer
76e5337592SStefano Zampini 
77a1cb98faSBarry Smith   Note:
785ae96e2bSMatthew G. Knepley   This function requires that tensor cells are ordered last.
79a1cb98faSBarry Smith 
802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()`
81e5337592SStefano Zampini @*/
82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
83d71ae5a4SJacob Faibussowitsch {
845ae96e2bSMatthew G. Knepley   DMLabel         ctLabel;
855ae96e2bSMatthew G. Knepley   IS              valueIS;
865ae96e2bSMatthew G. Knepley   const PetscInt *ctypes;
875ae96e2bSMatthew G. Knepley   PetscInt        Nct, cS = PETSC_MAX_INT, cE = 0;
88e5337592SStefano Zampini 
89e5337592SStefano Zampini   PetscFunctionBegin;
909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
915ae96e2bSMatthew G. Knepley   PetscCall(DMLabelGetValueIS(ctLabel, &valueIS));
925ae96e2bSMatthew G. Knepley   PetscCall(ISGetLocalSize(valueIS, &Nct));
935ae96e2bSMatthew G. Knepley   PetscCall(ISGetIndices(valueIS, &ctypes));
945ae96e2bSMatthew G. Knepley   if (!Nct) cS = cE = 0;
955ae96e2bSMatthew G. Knepley   for (PetscInt t = 0; t < Nct; ++t) {
96*c306944fSJed Brown     const DMPolytopeType ct = (DMPolytopeType)ctypes[t];
975ae96e2bSMatthew G. Knepley     PetscInt             ctS, ctE, ht;
985ae96e2bSMatthew G. Knepley 
995ae96e2bSMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) {
1005ae96e2bSMatthew G. Knepley       // If any cells are not typed, just use all cells
1015ae96e2bSMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd));
1025ae96e2bSMatthew G. Knepley       break;
1035ae96e2bSMatthew G. Knepley     }
104*c306944fSJed Brown     if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue;
1055ae96e2bSMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE));
1065ae96e2bSMatthew G. Knepley     if (ctS >= ctE) continue;
1075ae96e2bSMatthew G. Knepley     // Check that a point has the right height
1085ae96e2bSMatthew G. Knepley     PetscCall(DMPlexGetPointHeight(dm, ctS, &ht));
1095ae96e2bSMatthew G. Knepley     if (ht != height) continue;
1105ae96e2bSMatthew G. Knepley     cS = PetscMin(cS, ctS);
1115ae96e2bSMatthew G. Knepley     cE = PetscMax(cE, ctE);
1125ae96e2bSMatthew G. Knepley   }
1135ae96e2bSMatthew G. Knepley   PetscCall(ISDestroy(&valueIS));
114695799ffSMatthew G. Knepley   // Reset label for fast lookup
115695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
116412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
117412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119e5337592SStefano Zampini }
120e5337592SStefano Zampini 
1219c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft)
1229c600e38SMatt McGurn {
1239c600e38SMatt McGurn   PetscInt                 cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t;
1249c600e38SMatt McGurn   PetscInt                *sStart, *sEnd;
1259c600e38SMatt McGurn   PetscViewerVTKFieldType *ft;
1269c600e38SMatt McGurn   PetscInt                 vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1];
1279c600e38SMatt McGurn   DMLabel                  depthLabel, ctLabel;
1289c600e38SMatt McGurn 
1299c600e38SMatt McGurn   PetscFunctionBegin;
1309c600e38SMatt McGurn 
1319c600e38SMatt McGurn   /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */
1329c600e38SMatt McGurn   PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1));
1339c600e38SMatt McGurn   PetscCall(DMGetCoordinateDim(dm, &cdim));
1349c600e38SMatt McGurn   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1359c600e38SMatt McGurn   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1369c600e38SMatt McGurn   if (field >= 0) {
1379c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES]));
1389c600e38SMatt McGurn   } else {
1399c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES]));
1409c600e38SMatt McGurn   }
1419c600e38SMatt McGurn 
1429c600e38SMatt McGurn   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
1439c600e38SMatt McGurn   PetscCall(DMPlexGetDepth(dm, &depth));
1449c600e38SMatt McGurn   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
1459c600e38SMatt McGurn   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
1469c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1479c600e38SMatt McGurn     const DMPolytopeType ict = (DMPolytopeType)c;
1489c600e38SMatt McGurn     PetscInt             dep;
1499c600e38SMatt McGurn 
1509c600e38SMatt McGurn     if (ict == DM_POLYTOPE_FV_GHOST) continue;
1519c600e38SMatt McGurn     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1529c600e38SMatt McGurn     if (pStart >= 0) {
1539c600e38SMatt McGurn       PetscCall(DMLabelGetValue(depthLabel, cStart, &dep));
1549c600e38SMatt McGurn       if (dep != depth - cellHeight) continue;
1559c600e38SMatt McGurn     }
1569c600e38SMatt McGurn     if (field >= 0) {
1579c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c]));
1589c600e38SMatt McGurn     } else {
1599c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c]));
1609c600e38SMatt McGurn     }
1619c600e38SMatt McGurn     PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1629c600e38SMatt McGurn   }
1639c600e38SMatt McGurn 
1649c600e38SMatt McGurn   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1659c600e38SMatt McGurn   *types = 0;
1669c600e38SMatt McGurn 
1679c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) {
1689c600e38SMatt McGurn     if (globalvcdof[c]) ++(*types);
1699c600e38SMatt McGurn   }
1709c600e38SMatt McGurn 
1719c600e38SMatt McGurn   PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft));
1729c600e38SMatt McGurn   t = 0;
1739c600e38SMatt McGurn   if (globalvcdof[DM_NUM_POLYTOPES]) {
1749c600e38SMatt McGurn     sStart[t] = vStart;
1759c600e38SMatt McGurn     sEnd[t]   = vEnd;
1769c600e38SMatt McGurn     ft[t]     = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
1779c600e38SMatt McGurn     ++t;
1789c600e38SMatt McGurn   }
1799c600e38SMatt McGurn 
1809c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1819c600e38SMatt McGurn     if (globalvcdof[c]) {
1829c600e38SMatt McGurn       const DMPolytopeType ict = (DMPolytopeType)c;
1839c600e38SMatt McGurn 
1849c600e38SMatt McGurn       PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1859c600e38SMatt McGurn       sStart[t] = cStart;
1869c600e38SMatt McGurn       sEnd[t]   = cEnd;
1879c600e38SMatt McGurn       ft[t]     = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD;
1889c600e38SMatt McGurn       ++t;
1899c600e38SMatt McGurn     }
1909c600e38SMatt McGurn   }
1919c600e38SMatt McGurn 
1929c600e38SMatt McGurn   if (!(*types)) {
1939c600e38SMatt McGurn     if (field >= 0) {
1949c600e38SMatt McGurn       const char *fieldname;
1959c600e38SMatt McGurn 
1969c600e38SMatt McGurn       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
1979c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
1989c600e38SMatt McGurn     } else {
1999c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
2009c600e38SMatt McGurn     }
2019c600e38SMatt McGurn   }
2029c600e38SMatt McGurn 
2039c600e38SMatt McGurn   *ssStart = sStart;
2049c600e38SMatt McGurn   *ssEnd   = sEnd;
2059c600e38SMatt McGurn   *sft     = ft;
2069c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2079c600e38SMatt McGurn }
2089c600e38SMatt McGurn 
2099c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft)
2109c600e38SMatt McGurn {
2119c600e38SMatt McGurn   PetscFunctionBegin;
2129c600e38SMatt McGurn   PetscCall(PetscFree3(*sStart, *sEnd, *ft));
2139c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2149c600e38SMatt McGurn }
2159c600e38SMatt McGurn 
216d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
217d71ae5a4SJacob Faibussowitsch {
218412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
219a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
2207e42fee7SMatthew G. Knepley 
2217e42fee7SMatthew G. Knepley   PetscFunctionBegin;
222e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
2239566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
2249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
2269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
2277e42fee7SMatthew G. Knepley   if (field >= 0) {
2289566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
2299566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
2307e42fee7SMatthew G. Knepley   } else {
2319566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
2329566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
2337e42fee7SMatthew G. Knepley   }
234712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
235a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
2367e42fee7SMatthew G. Knepley     *sStart = vStart;
2377e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
238f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
2397e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
240a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
2417e42fee7SMatthew G. Knepley     *sStart = cStart;
2427e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
243f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
2447e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
245e630c359SToby Isaac   } else {
246e630c359SToby Isaac     if (field >= 0) {
247e630c359SToby Isaac       const char *fieldname;
248e630c359SToby Isaac 
2499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
25063a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
251e630c359SToby Isaac     } else {
25263a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
253e630c359SToby Isaac     }
254e630c359SToby Isaac   }
2553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2567e42fee7SMatthew G. Knepley }
2577e42fee7SMatthew G. Knepley 
2586913077dSMatthew G. Knepley /*@
2596913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
2606913077dSMatthew G. Knepley 
26120f4b53cSBarry Smith   Collective
2626913077dSMatthew G. Knepley 
2636913077dSMatthew G. Knepley   Input Parameters:
264a1cb98faSBarry Smith + dm     - The `DMPLEX` object
2656913077dSMatthew G. Knepley . n      - The number of vectors
2666913077dSMatthew G. Knepley . u      - The array of local vectors
267a1cb98faSBarry Smith - viewer - The `PetscViewer`
2686913077dSMatthew G. Knepley 
2696913077dSMatthew G. Knepley   Level: advanced
2706913077dSMatthew G. Knepley 
2711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
2726913077dSMatthew G. Knepley @*/
273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
274d71ae5a4SJacob Faibussowitsch {
2756913077dSMatthew G. Knepley   PetscDS            ds;
2766913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
2776913077dSMatthew G. Knepley   PetscDrawLG        lg;
2786913077dSMatthew G. Knepley   Vec                coordinates;
2796913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
2806913077dSMatthew G. Knepley   PetscReal         *vals;
2816913077dSMatthew G. Knepley   PetscInt          *Nc;
2826913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
2836913077dSMatthew G. Knepley   char             **names;
2846913077dSMatthew G. Knepley 
2856913077dSMatthew G. Knepley   PetscFunctionBegin;
2869566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
2879566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2889566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
2899566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2906913077dSMatthew G. Knepley 
2919566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2923ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
2939566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
2946913077dSMatthew G. Knepley 
2959566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
2966913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
2976913077dSMatthew G. Knepley     const char *vname;
2986913077dSMatthew G. Knepley 
2999566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
3006913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
3016913077dSMatthew G. Knepley       PetscObject disc;
3026913077dSMatthew G. Knepley       const char *fname;
3036913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
3046913077dSMatthew G. Knepley 
3059566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
3066913077dSMatthew G. Knepley       /* TODO Create names for components */
3076913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
3089566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
309c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
310c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
311c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
3129566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
3136913077dSMatthew G. Knepley       }
3146913077dSMatthew G. Knepley     }
3156913077dSMatthew G. Knepley   }
3169566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
3176913077dSMatthew G. Knepley   /* Just add P_1 support for now */
3189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3209566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
3219566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
3226913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
3236913077dSMatthew G. Knepley     PetscScalar *x, *svals;
3246913077dSMatthew G. Knepley 
3259566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
3266913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
3279566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
3286913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
3296913077dSMatthew G. Knepley     }
3309566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
3316913077dSMatthew G. Knepley   }
3329566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
3339566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
3349566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
3359566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
3366913077dSMatthew G. Knepley 
3379566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
3389566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
3393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3406913077dSMatthew G. Knepley }
3416913077dSMatthew G. Knepley 
342d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
343d71ae5a4SJacob Faibussowitsch {
3446913077dSMatthew G. Knepley   DM dm;
3456913077dSMatthew G. Knepley 
3466913077dSMatthew G. Knepley   PetscFunctionBegin;
3479566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
3489566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
3493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3506913077dSMatthew G. Knepley }
3516913077dSMatthew G. Knepley 
352d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
353d71ae5a4SJacob Faibussowitsch {
354e412dcbdSMatthew G. Knepley   DM                 dm;
355d1df6f1dSMatthew G. Knepley   PetscSection       s;
356e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
357e412dcbdSMatthew G. Knepley   DM                 cdm;
358e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
359e412dcbdSMatthew G. Knepley   Vec                coordinates;
360c9c77995SMatthew G. Knepley   const PetscScalar *array;
361c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
362339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
3636913077dSMatthew G. Knepley   PetscBool          flg;
364d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
365e412dcbdSMatthew G. Knepley   const char        *name;
366339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
367e412dcbdSMatthew G. Knepley 
368e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
3699566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3709566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3719566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3729566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
3739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
3749566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
3759566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
3769566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
3779566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
380e412dcbdSMatthew G. Knepley 
3819566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
3829566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
383e412dcbdSMatthew G. Knepley 
3849566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
385c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
3869566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
387e412dcbdSMatthew G. Knepley 
388d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
389d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
390d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
391d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
392d1df6f1dSMatthew G. Knepley     IS          fis;
393d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
394d1df6f1dSMatthew G. Knepley     const char *fname;
395d1df6f1dSMatthew G. Knepley 
3969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
3979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
398d1df6f1dSMatthew G. Knepley 
3999566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
400ad540459SPierre Jolivet     else prefix[0] = '\0';
401d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4029566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
4039566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
4049566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
4059566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
406d1df6f1dSMatthew G. Knepley     }
407d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
408d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
409d1df6f1dSMatthew G. Knepley 
4109566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
41163a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
41263a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
4139566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
414d1df6f1dSMatthew G. Knepley 
415d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
4169566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
417339e3443SMatthew G. Knepley       if (!flg) {
4189566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
4199566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
420d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
421339e3443SMatthew G. Knepley       }
422c9c77995SMatthew G. Knepley 
4239566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
4249566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
425c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
4269566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
427e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
42899a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
429c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
430c9c77995SMatthew G. Knepley         PetscBool          isDG;
431e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
432e412dcbdSMatthew G. Knepley 
4339566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
434339e3443SMatthew G. Knepley         if (a) {
435d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
436339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
437339e3443SMatthew G. Knepley         } else {
438339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
439339e3443SMatthew G. Knepley           PetscInt     numVals, va;
440339e3443SMatthew G. Knepley 
4419566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
44263a3b9bcSJacob Faibussowitsch           PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals);
443d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
444d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
445d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
446d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
447339e3443SMatthew G. Knepley             break;
448d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
449d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
450d1df6f1dSMatthew 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]);
451d1df6f1dSMatthew G. Knepley             break;
452d71ae5a4SJacob Faibussowitsch           default:
453d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
454339e3443SMatthew G. Knepley           }
4559566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
456339e3443SMatthew G. Knepley         }
457c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
458e412dcbdSMatthew G. Knepley         switch (numCoords) {
459e412dcbdSMatthew G. Knepley         case 6:
4609edc3542SMatthew Knepley         case 12: /* Localized triangle */
4619566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
462e412dcbdSMatthew G. Knepley           break;
463e412dcbdSMatthew G. Knepley         case 8:
4649edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
4659566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
4669566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]));
467e412dcbdSMatthew G. Knepley           break;
468d71ae5a4SJacob Faibussowitsch         default:
469d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
470e412dcbdSMatthew G. Knepley         }
471c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
472e412dcbdSMatthew G. Knepley       }
4739566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
4749566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
4759566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
4769566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
477d1df6f1dSMatthew G. Knepley     }
478d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4799566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
4809566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
4819566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
482d1df6f1dSMatthew G. Knepley     }
483d1df6f1dSMatthew G. Knepley   }
4843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485e412dcbdSMatthew G. Knepley }
486e412dcbdSMatthew G. Knepley 
487d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
488d71ae5a4SJacob Faibussowitsch {
4896913077dSMatthew G. Knepley   DM        dm;
4906913077dSMatthew G. Knepley   PetscDraw draw;
4916913077dSMatthew G. Knepley   PetscInt  dim;
4926913077dSMatthew G. Knepley   PetscBool isnull;
4936913077dSMatthew G. Knepley 
4946913077dSMatthew G. Knepley   PetscFunctionBegin;
4959566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4969566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4973ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
4986913077dSMatthew G. Knepley 
4999566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
5009566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
5016913077dSMatthew G. Knepley   switch (dim) {
502d71ae5a4SJacob Faibussowitsch   case 1:
503d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
504d71ae5a4SJacob Faibussowitsch     break;
505d71ae5a4SJacob Faibussowitsch   case 2:
506d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
507d71ae5a4SJacob Faibussowitsch     break;
508d71ae5a4SJacob Faibussowitsch   default:
509d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
5106913077dSMatthew G. Knepley   }
5113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5126913077dSMatthew G. Knepley }
5136913077dSMatthew G. Knepley 
514d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
515d71ae5a4SJacob Faibussowitsch {
516684b87d9SLisandro Dalcin   DM                      dm;
517684b87d9SLisandro Dalcin   Vec                     locv;
518684b87d9SLisandro Dalcin   const char             *name;
519684b87d9SLisandro Dalcin   PetscSection            section;
520684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
521e630c359SToby Isaac   PetscInt                numFields;
522684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
523684b87d9SLisandro Dalcin 
524684b87d9SLisandro Dalcin   PetscFunctionBegin;
5259566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
5269566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
5279566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
5289566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
5299566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
5309566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
5319566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
532e630c359SToby Isaac   if (!numFields) {
5339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
5349566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
535e630c359SToby Isaac   } else {
536e630c359SToby Isaac     PetscInt f;
537e630c359SToby Isaac 
538e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
5399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
540e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
5419566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
5429566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
543e630c359SToby Isaac     }
5449566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
545e630c359SToby Isaac   }
5463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
547684b87d9SLisandro Dalcin }
548684b87d9SLisandro Dalcin 
549d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
550d71ae5a4SJacob Faibussowitsch {
551552f7358SJed Brown   DM        dm;
5525f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
553552f7358SJed Brown 
554552f7358SJed Brown   PetscFunctionBegin;
5559566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
55628b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5615f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5625f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
563684b87d9SLisandro Dalcin     PetscInt    i, numFields;
564684b87d9SLisandro Dalcin     PetscObject fe;
565ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
566684b87d9SLisandro Dalcin     Vec         locv = v;
567684b87d9SLisandro Dalcin     const char *name;
568684b87d9SLisandro Dalcin     PetscInt    step;
569684b87d9SLisandro Dalcin     PetscReal   time;
570ef31f671SMatthew G. Knepley 
5719566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
572684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
5739566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
5749371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
5759371c9d4SSatish Balay         fem = PETSC_TRUE;
5769371c9d4SSatish Balay         break;
5779371c9d4SSatish Balay       }
578ef31f671SMatthew G. Knepley     }
579684b87d9SLisandro Dalcin     if (fem) {
580798534f6SMatthew G. Knepley       PetscObject isZero;
581798534f6SMatthew G. Knepley 
5829566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
5839566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
5849566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
5859566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5869566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5879566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
5889566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
5899566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
590ef31f671SMatthew G. Knepley     }
591552f7358SJed Brown     if (isvtk) {
5929566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
593b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
594b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5959566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
596b136c2c9SMatthew G. Knepley #else
597b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
598b136c2c9SMatthew G. Knepley #endif
599f13a32a3SMatthew G. Knepley     } else if (isdraw) {
6009566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
601684b87d9SLisandro Dalcin     } else if (isglvis) {
6029566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
6039566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
6049566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
6055f34f2dcSJed Brown     } else if (iscgns) {
6065f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
6075f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
6085f34f2dcSJed Brown #else
6095f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
6105f34f2dcSJed Brown #endif
611684b87d9SLisandro Dalcin     }
612798534f6SMatthew G. Knepley     if (fem) {
6139566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6149566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
615798534f6SMatthew G. Knepley     }
616552f7358SJed Brown   } else {
617684b87d9SLisandro Dalcin     PetscBool isseq;
618684b87d9SLisandro Dalcin 
6199566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6209566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6219566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
622552f7358SJed Brown   }
6233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
624552f7358SJed Brown }
625552f7358SJed Brown 
626d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
627d71ae5a4SJacob Faibussowitsch {
628552f7358SJed Brown   DM        dm;
6295f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
630552f7358SJed Brown 
631552f7358SJed Brown   PetscFunctionBegin;
6329566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63328b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
6385f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
6399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6405f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
641552f7358SJed Brown     Vec         locv;
642798534f6SMatthew G. Knepley     PetscObject isZero;
643552f7358SJed Brown     const char *name;
644552f7358SJed Brown 
6459566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
6469566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6479566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
6489566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6499566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6509566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6519566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6529566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
6539566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6549566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
655b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
656b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6579566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
658b136c2c9SMatthew G. Knepley #else
659b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
660b136c2c9SMatthew G. Knepley #endif
6616823f3c5SBlaise Bourdin   } else if (isexodusii) {
6626823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6639566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
6646823f3c5SBlaise Bourdin #else
6656823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6666823f3c5SBlaise Bourdin #endif
667552f7358SJed Brown   } else {
668684b87d9SLisandro Dalcin     PetscBool isseq;
669684b87d9SLisandro Dalcin 
6709566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6719566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6729566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
673552f7358SJed Brown   }
6743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
675552f7358SJed Brown }
676552f7358SJed Brown 
677d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
678d71ae5a4SJacob Faibussowitsch {
679d930f514SMatthew G. Knepley   DM                dm;
680d930f514SMatthew G. Knepley   MPI_Comm          comm;
681d930f514SMatthew G. Knepley   PetscViewerFormat format;
682d930f514SMatthew G. Knepley   Vec               v;
683d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
684d930f514SMatthew G. Knepley 
685d930f514SMatthew G. Knepley   PetscFunctionBegin;
6869566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
6879566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
68828b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6899566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
692d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
693a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
694a8ad634aSStefano Zampini     /* this need a better fix */
695a8ad634aSStefano Zampini     if (dm->useNatural) {
696a8ad634aSStefano Zampini       if (dm->sfNatural) {
697d930f514SMatthew G. Knepley         const char *vecname;
698d930f514SMatthew G. Knepley         PetscInt    n, nroots;
699d930f514SMatthew G. Knepley 
7009566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
7019566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
702d930f514SMatthew G. Knepley         if (n == nroots) {
703f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
7049566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
7059566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
7069566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7079566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
708d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
709d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
710a8ad634aSStefano Zampini     } else v = originalv;
711a8ad634aSStefano Zampini   } else v = originalv;
712a8ad634aSStefano Zampini 
713d930f514SMatthew G. Knepley   if (ishdf5) {
714d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7159566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
716d930f514SMatthew G. Knepley #else
717d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
718d930f514SMatthew G. Knepley #endif
719d930f514SMatthew G. Knepley   } else if (isvtk) {
720d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
721d930f514SMatthew G. Knepley   } else {
722d930f514SMatthew G. Knepley     PetscBool isseq;
723d930f514SMatthew G. Knepley 
7249566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7259566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
7269566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
727d930f514SMatthew G. Knepley   }
728f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
7293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
730d930f514SMatthew G. Knepley }
731d930f514SMatthew G. Knepley 
732d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
733d71ae5a4SJacob Faibussowitsch {
7342c40f234SMatthew G. Knepley   DM        dm;
7352c40f234SMatthew G. Knepley   PetscBool ishdf5;
7362c40f234SMatthew G. Knepley 
7372c40f234SMatthew G. Knepley   PetscFunctionBegin;
7389566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
73928b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7412c40f234SMatthew G. Knepley   if (ishdf5) {
7422c40f234SMatthew G. Knepley     DM          dmBC;
7432c40f234SMatthew G. Knepley     Vec         gv;
7442c40f234SMatthew G. Knepley     const char *name;
7452c40f234SMatthew G. Knepley 
7469566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
7479566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
7489566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
7499566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
7509566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
7519566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
7529566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
7539566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
7541baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7562c40f234SMatthew G. Knepley }
7572c40f234SMatthew G. Knepley 
758d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
759d71ae5a4SJacob Faibussowitsch {
7602c40f234SMatthew G. Knepley   DM        dm;
7616823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
7622c40f234SMatthew G. Knepley 
7632c40f234SMatthew G. Knepley   PetscFunctionBegin;
7649566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
76528b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
7682c40f234SMatthew G. Knepley   if (ishdf5) {
769878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7709566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
771b136c2c9SMatthew G. Knepley #else
772b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
773878b459fSMatthew G. Knepley #endif
7746823f3c5SBlaise Bourdin   } else if (isexodusii) {
7756823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
7769566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
7776823f3c5SBlaise Bourdin #else
7786823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
7796823f3c5SBlaise Bourdin #endif
7801baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
782552f7358SJed Brown }
783552f7358SJed Brown 
784d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
785d71ae5a4SJacob Faibussowitsch {
786d930f514SMatthew G. Knepley   DM                dm;
787d930f514SMatthew G. Knepley   PetscViewerFormat format;
788d930f514SMatthew G. Knepley   PetscBool         ishdf5;
789d930f514SMatthew G. Knepley 
790d930f514SMatthew G. Knepley   PetscFunctionBegin;
7919566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
79228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7939566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7949566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
795d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
796a8ad634aSStefano Zampini     if (dm->useNatural) {
797d930f514SMatthew G. Knepley       if (dm->sfNatural) {
798d930f514SMatthew G. Knepley         if (ishdf5) {
799d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
800d930f514SMatthew G. Knepley           Vec         v;
801d930f514SMatthew G. Knepley           const char *vecname;
802d930f514SMatthew G. Knepley 
803f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
8049566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
8059566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
8069566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
8079566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
8089566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
809f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
810d930f514SMatthew G. Knepley #else
811d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
812d930f514SMatthew G. Knepley #endif
813d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
814d930f514SMatthew G. Knepley       }
8151baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
816d930f514SMatthew G. Knepley   }
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818d930f514SMatthew G. Knepley }
819d930f514SMatthew G. Knepley 
820d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
821d71ae5a4SJacob Faibussowitsch {
822731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
823731e8ddeSMatthew G. Knepley   Vec                coordinates;
824ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
825731e8ddeSMatthew G. Knepley   const char        *name[4];
826731e8ddeSMatthew G. Knepley   const PetscScalar *a;
827731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
828731e8ddeSMatthew G. Knepley 
829731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
8309566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8329566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
8349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
8359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8379566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
838731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
839731e8ddeSMatthew G. Knepley   name[1]       = "edge";
840731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
841731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
842731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
843731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
844ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
845731e8ddeSMatthew G. Knepley 
8469566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
84763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
8489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
850731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
851731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
852731e8ddeSMatthew G. Knepley 
853731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
8549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
855731e8ddeSMatthew G. Knepley       if (!dof) continue;
8569566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
8579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
85863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
859731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
8609566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
861731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
8629566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
8639566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
864731e8ddeSMatthew G. Knepley         }
8659566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
866731e8ddeSMatthew G. Knepley       }
8679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
868731e8ddeSMatthew G. Knepley     }
8699566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
871731e8ddeSMatthew G. Knepley   }
8729566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
8733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
874731e8ddeSMatthew G. Knepley }
875731e8ddeSMatthew G. Knepley 
8769371c9d4SSatish Balay typedef enum {
8779371c9d4SSatish Balay   CS_CARTESIAN,
8789371c9d4SSatish Balay   CS_POLAR,
8799371c9d4SSatish Balay   CS_CYLINDRICAL,
8809371c9d4SSatish Balay   CS_SPHERICAL
8819371c9d4SSatish Balay } CoordSystem;
88219ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
88319ad8254SMatthew G. Knepley 
884d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
885d71ae5a4SJacob Faibussowitsch {
88619ad8254SMatthew G. Knepley   PetscInt i;
88719ad8254SMatthew G. Knepley 
88819ad8254SMatthew G. Knepley   PetscFunctionBegin;
88919ad8254SMatthew G. Knepley   if (dim > 3) {
8909566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
89119ad8254SMatthew G. Knepley   } else {
892bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
89319ad8254SMatthew G. Knepley 
89419ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
89519ad8254SMatthew G. Knepley     switch (cs) {
8969371c9d4SSatish Balay     case CS_CARTESIAN:
8979371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
8989371c9d4SSatish Balay       break;
89919ad8254SMatthew G. Knepley     case CS_POLAR:
90063a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
90119ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90219ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90319ad8254SMatthew G. Knepley       break;
90419ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
90563a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
90619ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90719ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90819ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
90919ad8254SMatthew G. Knepley       break;
91019ad8254SMatthew G. Knepley     case CS_SPHERICAL:
91163a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
91219ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
91319ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
91419ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
91519ad8254SMatthew G. Knepley       break;
91619ad8254SMatthew G. Knepley     }
9179566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
91819ad8254SMatthew G. Knepley   }
9193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92019ad8254SMatthew G. Knepley }
92119ad8254SMatthew G. Knepley 
922d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
923d71ae5a4SJacob Faibussowitsch {
924552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
9256858538eSMatthew G. Knepley   DM                cdm, cdmCell;
9266858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
9276858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
928552f7358SJed Brown   PetscViewerFormat format;
929552f7358SJed Brown 
930552f7358SJed Brown   PetscFunctionBegin;
9319566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
932552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
933552f7358SJed Brown     const char *name;
934f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
9359318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
936552f7358SJed Brown     PetscMPIInt rank, size;
937552f7358SJed Brown 
9389f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9399f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9409f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9419f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9429f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9439f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9459566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9469566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
9479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
9499566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
95163a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
95263a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
95363a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
95463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
9559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
95663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
957552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
958552f7358SJed Brown       PetscInt dof, off, s;
959552f7358SJed Brown 
9609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
9619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
96248a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
963552f7358SJed Brown     }
9649566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
96563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
96663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
967552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
968552f7358SJed Brown       PetscInt dof, off, c;
969552f7358SJed Brown 
9709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
9719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
97248a46eb9SPierre Jolivet       for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
973552f7358SJed Brown     }
9749566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
9759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9763d2e540fSStefano Zampini     if (coordSection && coordinates) {
97719ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
9786858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
9796858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
98019ad8254SMatthew G. Knepley       PetscMPIInt        rank;
98119ad8254SMatthew G. Knepley       const char        *name;
98219ad8254SMatthew G. Knepley 
9839566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
9849566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
9859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
98663a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
9879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
9886858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
9896858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
9906858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
9916858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
9929566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
99363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
99463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
9959566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
99619ad8254SMatthew G. Knepley 
9979566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
9986858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
9999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
10009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
100119ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
100219ad8254SMatthew G. Knepley         PetscInt dof, off;
100319ad8254SMatthew G. Knepley 
10046858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
10059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
10069566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
10076858538eSMatthew G. Knepley           if (dof) {
100863a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10099566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
10109566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
101119ad8254SMatthew G. Knepley           }
10126858538eSMatthew G. Knepley         }
10136858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
10146858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
10156858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
10166858538eSMatthew G. Knepley           if (dof) {
10176858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10186858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
10196858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
10206858538eSMatthew G. Knepley           }
10216858538eSMatthew G. Knepley         }
10226858538eSMatthew G. Knepley       }
10239566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
10249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
10259566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
10266858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
10273d2e540fSStefano Zampini     }
10289566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10299566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
10309318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
10319318fe57SMatthew G. Knepley       DMLabel     label;
10329318fe57SMatthew G. Knepley       PetscBool   isdepth;
10339318fe57SMatthew G. Knepley       const char *name;
10349318fe57SMatthew G. Knepley 
10359566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
10369566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
10379318fe57SMatthew G. Knepley       if (isdepth) continue;
10389566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
10399566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
10409318fe57SMatthew G. Knepley     }
1041552f7358SJed Brown     if (size > 1) {
1042552f7358SJed Brown       PetscSF sf;
1043552f7358SJed Brown 
10449566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
10459566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
1046552f7358SJed Brown     }
10474e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
10489566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1049552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
10500588280cSMatthew G. Knepley     const char  *name, *color;
10510588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
10520588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
1053fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
1054552f7358SJed Brown     PetscReal    scale      = 2.0;
105578081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
1056b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
10570588280cSMatthew G. Knepley     double       tcoords[3];
1058552f7358SJed Brown     PetscScalar *coords;
1059b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
1060552f7358SJed Brown     PetscMPIInt  rank, size;
10610588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
1062b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
1063fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
1064fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
1065552f7358SJed Brown 
10669f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
10679f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
10689f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10699f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
10709f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
10719f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
10729566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
10739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
10749566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10750588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
10760588280cSMatthew G. Knepley     numColors  = 10;
10770588280cSMatthew G. Knepley     numLColors = 10;
10789566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
10799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
10809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
10819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
1082b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
1083b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
1084b7f6ffafSMatthew G. Knepley     n = 4;
10859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
10861dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
10879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
10881dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
10899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
10900588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
10919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
10920588280cSMatthew G. Knepley     if (!useColors) {
10930588280cSMatthew G. Knepley       numColors = 3;
10949566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
10950588280cSMatthew G. Knepley     }
10969566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
10970588280cSMatthew G. Knepley     if (!useColors) {
10980588280cSMatthew G. Knepley       numLColors = 4;
10999566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
11000588280cSMatthew G. Knepley     }
11019566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
1102b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
11039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
11041dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1105202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
11069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1107fe1cc32dSStefano Zampini 
1108fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
11099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
11109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
11119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
11129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1113fe1cc32dSStefano Zampini     if (lflg) {
1114fe1cc32dSStefano Zampini       DMLabel lbl;
1115fe1cc32dSStefano Zampini 
11169566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1117fe1cc32dSStefano Zampini       if (lbl) {
1118fe1cc32dSStefano Zampini         PetscInt val, defval;
1119fe1cc32dSStefano Zampini 
11209566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
11219566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1122fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1123fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1124fe1cc32dSStefano Zampini           PetscInt  closureSize;
1125fe1cc32dSStefano Zampini 
11269566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1127fe1cc32dSStefano Zampini           if (val == defval) continue;
1128fe1cc32dSStefano Zampini 
11299566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
113048a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
11319566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1132fe1cc32dSStefano Zampini         }
1133fe1cc32dSStefano Zampini       }
1134fe1cc32dSStefano Zampini     }
1135fe1cc32dSStefano Zampini 
11369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
11379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
11389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
11399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
11400588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1141552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1142552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1143552f7358SJed Brown \\usetikzlibrary{arrows}\n\
11445f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
11450588280cSMatthew G. Knepley     if (size > 1) {
11469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1147770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
114863a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
114963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1150770b213bSMatthew G Knepley       }
11519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
11520588280cSMatthew G. Knepley     }
1153b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1154b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1155b7f6ffafSMatthew G. Knepley 
115663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
115763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
115863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
11599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
116063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
116163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
11629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
116363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
116463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
116563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
116663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
11679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1168b7f6ffafSMatthew G. Knepley     }
11699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1170fe1cc32dSStefano Zampini 
1171552f7358SJed Brown     /* Plot vertices */
11729566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
11739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1174552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1175552f7358SJed Brown       PetscInt  off, dof, d;
11760588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1177552f7358SJed Brown 
1178fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
11799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
11809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
11819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
118263a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
11830588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11840588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1185c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
11860588280cSMatthew G. Knepley       }
11870588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
11889371c9d4SSatish Balay       if (dim == 3) {
11899371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
11909371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
11919371c9d4SSatish Balay         tcoords[2]    = -tmp;
11929371c9d4SSatish Balay       }
1193552f7358SJed Brown       for (d = 0; d < dof; ++d) {
11949566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11959566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1196552f7358SJed Brown       }
1197b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1198b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
11990588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
12000588280cSMatthew G. Knepley         PetscInt val;
12019566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
12029371c9d4SSatish Balay         if (val >= 0) {
12039371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12049371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12059371c9d4SSatish Balay           break;
12069371c9d4SSatish Balay         }
12070588280cSMatthew G. Knepley       }
1208b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
120963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1210b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
121163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
12121baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1213552f7358SJed Brown     }
12149566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12159566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1216b7f6ffafSMatthew G. Knepley     /* Plot edges */
1217b7f6ffafSMatthew G. Knepley     if (plotEdges) {
12189566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
12199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1220b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1221b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1222b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1223b7f6ffafSMatthew G. Knepley 
1224b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
12259566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
122663a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
12279566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
12289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
12299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
12309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
12319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1232b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1233b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1234b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1235b7f6ffafSMatthew G. Knepley         }
1236b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12379371c9d4SSatish Balay         if (dim == 3) {
12389371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12399371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12409371c9d4SSatish Balay           tcoords[2]    = -tmp;
12419371c9d4SSatish Balay         }
1242b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12439566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12449566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1245b7f6ffafSMatthew G. Knepley         }
1246b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1247b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1248b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1249b7f6ffafSMatthew G. Knepley           PetscInt val;
12509566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
12519371c9d4SSatish Balay           if (val >= 0) {
12529371c9d4SSatish Balay             color = lcolors[l % numLColors];
12539371c9d4SSatish Balay             break;
12549371c9d4SSatish Balay           }
1255b7f6ffafSMatthew G. Knepley         }
125663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1257b7f6ffafSMatthew G. Knepley       }
12589566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
12599566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
12609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1261b7f6ffafSMatthew G. Knepley     }
1262846a3e8bSMatthew G. Knepley     /* Plot cells */
1263b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1264846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1265846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1266846a3e8bSMatthew G. Knepley 
1267fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1268846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1269846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1270846a3e8bSMatthew G. Knepley           PetscInt val;
12719566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12729371c9d4SSatish Balay           if (val >= 0) {
12739371c9d4SSatish Balay             color = lcolors[l % numLColors];
12749371c9d4SSatish Balay             break;
12759371c9d4SSatish Balay           }
1276846a3e8bSMatthew G. Knepley         }
12779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
127863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1279846a3e8bSMatthew G. Knepley       }
1280846a3e8bSMatthew G. Knepley     } else {
1281b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1282846a3e8bSMatthew G. Knepley 
1283b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1284b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1285fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
12869566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1287*c306944fSJed Brown         if (DMPolytopeTypeIsHybrid(ct)) {
1288b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1289b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1290b7f6ffafSMatthew G. Knepley 
12919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
12929566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1293b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1294b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1295b7f6ffafSMatthew G. Knepley 
12969566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
129763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank));
1298b7f6ffafSMatthew G. Knepley           }
1299b7f6ffafSMatthew G. Knepley         } else {
1300b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1301b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1302b7f6ffafSMatthew G. Knepley 
13039566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1304846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1305846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1306846a3e8bSMatthew G. Knepley 
1307b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1308846a3e8bSMatthew G. Knepley           }
13099566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1310b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1311b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1312b7f6ffafSMatthew G. Knepley 
1313b7f6ffafSMatthew G. Knepley             if (v > 0) {
1314b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1315b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1316b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1317b7f6ffafSMatthew G. Knepley 
13189371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
13199371c9d4SSatish Balay                 endpoints[1] = vertex;
13209566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
132163a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
132263a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
13239566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
13241baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1325b7f6ffafSMatthew G. Knepley             }
132663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1327b7f6ffafSMatthew G. Knepley           }
13289566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
13299566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1330846a3e8bSMatthew G. Knepley         }
1331846a3e8bSMatthew G. Knepley       }
1332b7f6ffafSMatthew G. Knepley     }
1333846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1334846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1335846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1336c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1337c713ec31SMatthew G. Knepley       const PetscScalar *array;
1338c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1339c713ec31SMatthew G. Knepley       PetscBool          isDG;
1340846a3e8bSMatthew G. Knepley 
1341fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1342c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1343c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1344c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
13459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1346c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1347c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1348c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1349846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1350846a3e8bSMatthew G. Knepley         }
1351846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
13529371c9d4SSatish Balay         if (cdim == 3) {
13539371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
13549371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
13559371c9d4SSatish Balay           tcoords[2]    = -tmp;
13569371c9d4SSatish Balay         }
1357ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1358846a3e8bSMatthew G. Knepley       }
1359ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1360c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1361c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
13629566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
13639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1364846a3e8bSMatthew G. Knepley       }
1365b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1366b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1367846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1368846a3e8bSMatthew G. Knepley         PetscInt val;
13699566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
13709371c9d4SSatish Balay         if (val >= 0) {
13719371c9d4SSatish Balay           color     = lcolors[l % numLColors];
13729371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
13739371c9d4SSatish Balay           break;
13749371c9d4SSatish Balay         }
1375846a3e8bSMatthew G. Knepley       }
1376b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
137763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1378b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
137963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
13801baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1381846a3e8bSMatthew G. Knepley     }
1382b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1383b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
13849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
13859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
13869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
13889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1389552f7358SJed Brown 
1390b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
13919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
13929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
13939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
13959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1396b7f6ffafSMatthew G. Knepley 
1397b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
13989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
13999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
14009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
14019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
14029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1403b7f6ffafSMatthew G. Knepley 
1404b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1405b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1406b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1407b7f6ffafSMatthew G. Knepley 
14089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
14099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
141048a46eb9SPierre Jolivet         for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
14110588280cSMatthew G. Knepley       }
14120588280cSMatthew G. Knepley     }
14139566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
14149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
14159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
141663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
14179566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
14189566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
14199566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
14209566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
14219566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
14220f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
14230f7d6e4aSStefano Zampini     Vec                    cown, acown;
14240f7d6e4aSStefano Zampini     VecScatter             sct;
14250f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
14260f7d6e4aSStefano Zampini     IS                     gid, acis;
14270f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
14280f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
14290f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
14300f7d6e4aSStefano Zampini     const PetscInt        *idxs;
14310f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
14320f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
14330f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
14340f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
14350f7d6e4aSStefano Zampini 
14369566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1438b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
14399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
14400f7d6e4aSStefano Zampini #endif
14410f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
14429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
14439566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
14440f7d6e4aSStefano Zampini       d1 = 0;
14459566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
14460f7d6e4aSStefano Zampini       nid = d2;
14479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
14489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
14499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
14500f7d6e4aSStefano Zampini     } else nid = 0.0;
14510f7d6e4aSStefano Zampini 
14520f7d6e4aSStefano Zampini     /* Get connectivity */
14539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14549566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
14550f7d6e4aSStefano Zampini 
14560f7d6e4aSStefano Zampini     /* filter overlapped local cells */
14579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
14589566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
14599566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
14609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
14610f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
14620f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
14630f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
14640f7d6e4aSStefano Zampini     }
14659566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
146663a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
14679566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14689566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
14690f7d6e4aSStefano Zampini 
14700f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
14719566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
14729566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
14739566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
14749566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
14750f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
14769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
14779566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
14789566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14799566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14809566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
14819566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
14829566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
14830f7d6e4aSStefano Zampini 
14840f7d6e4aSStefano Zampini     /* compute edgeCut */
14850f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
14869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
14879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
14889566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
14899566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14909566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
14910f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
14920f7d6e4aSStefano Zampini       PetscInt totl;
14930f7d6e4aSStefano Zampini 
14940f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
14959566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
14960f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
14970f7d6e4aSStefano Zampini         if (work[i] < 0) {
14980f7d6e4aSStefano Zampini           ect += 1;
14990f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
15000f7d6e4aSStefano Zampini         }
15010f7d6e4aSStefano Zampini       }
15020f7d6e4aSStefano Zampini     }
15039566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
15049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
15050f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
15060f7d6e4aSStefano Zampini     lm[1] = -numVertices;
15071c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
150863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0]));
15090f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
15100f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
15110f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
15121c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
151363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1514b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
151563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)(gm[1])) / ((double)gm[0]) : 1.));
15160f7d6e4aSStefano Zampini #else
151763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
15180f7d6e4aSStefano Zampini #endif
15199566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
15209566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
15219566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
15229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1523552f7358SJed Brown   } else {
1524412e9a14SMatthew G. Knepley     const char    *name;
1525d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1526412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1527d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1528ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
15299318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1530412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1531412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1532552f7358SJed Brown 
15339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
15359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
15369566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
15379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
15389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
153963a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
154063a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
154163a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
15429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
15431c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
15442827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd));
1545d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
15469566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
15479566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1548412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1549412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1550412e9a14SMatthew G. Knepley 
15519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
15529566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1553412e9a14SMatthew G. Knepley       ict = ct0;
15549566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1555412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1556412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1557412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1558412e9a14SMatthew G. Knepley 
15599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1560412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1561412e9a14SMatthew G. Knepley         else ++Nc[1];
1562412e9a14SMatthew G. Knepley       }
1563ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
15649566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15659566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
15669566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
156763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1568834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1569dd400576SPatrick Sanan           if (rank == 0) {
157063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
157163a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
157263a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1573834065abSMatthew G. Knepley           }
1574cbb7f117SMark Adams         }
1575ca7bf7eeSMatthew G. Knepley       } else {
1576ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1577ca7bf7eeSMatthew G. Knepley 
15789371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
15799371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
15809566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15819371c9d4SSatish Balay         locMinMax[0] = Nc[1];
15829371c9d4SSatish Balay         locMinMax[1] = Nc[1];
15839566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1584ca7bf7eeSMatthew G. Knepley         if (d == depth) {
15859371c9d4SSatish Balay           locMinMax[0] = gcNum;
15869371c9d4SSatish Balay           locMinMax[1] = gcNum;
15879566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1588ca7bf7eeSMatthew G. Knepley         }
158963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
15909566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15919566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
15929566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1593ca7bf7eeSMatthew G. Knepley       }
15949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1595552f7358SJed Brown     }
15969566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
15979318fe57SMatthew G. Knepley     {
15989318fe57SMatthew G. Knepley       const PetscReal *maxCell;
15999318fe57SMatthew G. Knepley       const PetscReal *L;
16006858538eSMatthew G. Knepley       PetscBool        localized;
16019318fe57SMatthew G. Knepley 
16024fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
16039566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
16046858538eSMatthew G. Knepley       if (L || localized) {
16056858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
16069566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
16076858538eSMatthew G. Knepley         if (L) {
16086858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
16099318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
16106858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
16116858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
16129318fe57SMatthew G. Knepley           }
16136858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
16146858538eSMatthew G. Knepley         }
16156858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
16169566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16179318fe57SMatthew G. Knepley       }
16189318fe57SMatthew G. Knepley     }
16199566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
16209566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1621a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1622a57dd577SMatthew G Knepley       DMLabel         label;
1623a57dd577SMatthew G Knepley       const char     *name;
1624a57dd577SMatthew G Knepley       IS              valueIS;
1625a57dd577SMatthew G Knepley       const PetscInt *values;
1626a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1627a57dd577SMatthew G Knepley 
16289566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
16299566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
16309566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
163163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
16329566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
16339566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
16349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1635a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1636a57dd577SMatthew G Knepley         PetscInt size;
1637a57dd577SMatthew G Knepley 
16389566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
16399566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
164063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1641a57dd577SMatthew G Knepley       }
16429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
16439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16449566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
16459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1646a57dd577SMatthew G Knepley     }
1647c1cad2e7SMatthew G. Knepley     {
1648c1cad2e7SMatthew G. Knepley       char    **labelNames;
1649c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1650c1cad2e7SMatthew G. Knepley       PetscBool flg;
1651c1cad2e7SMatthew G. Knepley 
16529566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
16539566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1654c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1655c1cad2e7SMatthew G. Knepley         DMLabel label;
1656c1cad2e7SMatthew G. Knepley 
16579566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1658c1cad2e7SMatthew G. Knepley         if (flg) {
16599566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
16609566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1661c1cad2e7SMatthew G. Knepley         }
16629566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1663c1cad2e7SMatthew G. Knepley       }
16649566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1665c1cad2e7SMatthew G. Knepley     }
166634aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
166734aa8a36SMatthew G. Knepley     if (dm->Nf) {
166834aa8a36SMatthew G. Knepley       PetscInt f;
166934aa8a36SMatthew G. Knepley 
167034aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
167134aa8a36SMatthew G. Knepley         const char *name;
167234aa8a36SMatthew G. Knepley 
16739566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
16749566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
16759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
16769566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
167734aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
16789566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
16799566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
168034aa8a36SMatthew G. Knepley         } else {
16819566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
16829566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
168334aa8a36SMatthew G. Knepley         }
16849566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
168534aa8a36SMatthew G. Knepley       }
168634aa8a36SMatthew G. Knepley     }
16879566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
16888e7ff633SMatthew G. Knepley     if (cdm) {
16899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
16909f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
16919566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
16929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
16938e7ff633SMatthew G. Knepley     }
1694552f7358SJed Brown   }
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696552f7358SJed Brown }
1697552f7358SJed Brown 
1698d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1699d71ae5a4SJacob Faibussowitsch {
1700e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1701e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1702a12d352dSMatthew G. Knepley   PetscInt       cdim;
1703e5c487bfSMatthew G. Knepley 
1704e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
17079566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1708e5c487bfSMatthew G. Knepley   switch (ct) {
1709a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1710a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1711a12d352dSMatthew G. Knepley     switch (cdim) {
17129371c9d4SSatish Balay     case 1: {
1713a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1714a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1715a12d352dSMatthew G. Knepley 
17169566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
17179566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
17189566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
17199371c9d4SSatish Balay     } break;
17209371c9d4SSatish Balay     case 2: {
1721a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1722a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1723a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1724a12d352dSMatthew G. Knepley 
17259566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17269566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK));
17279566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK));
17289371c9d4SSatish Balay     } break;
1729d71ae5a4SJacob Faibussowitsch     default:
1730d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1731a12d352dSMatthew G. Knepley     }
1732a12d352dSMatthew G. Knepley     break;
1733e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
17349371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17369566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17379566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1738e5c487bfSMatthew G. Knepley     break;
1739e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
17409371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17419371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17459566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1746e5c487bfSMatthew G. Knepley     break;
17479f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
17489f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17499f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17509f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17519f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17529f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17539f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
17549f4ada15SMatthew G. Knepley     break;
1755d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1756d71ae5a4SJacob Faibussowitsch     break;
1757d71ae5a4SJacob Faibussowitsch   default:
1758d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1759e5c487bfSMatthew G. Knepley   }
17603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1761e5c487bfSMatthew G. Knepley }
1762e5c487bfSMatthew G. Knepley 
1763d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1764d71ae5a4SJacob Faibussowitsch {
1765e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1766e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1767e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1768e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1769e5c487bfSMatthew G. Knepley 
1770e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17719566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1773e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1774e5c487bfSMatthew G. Knepley   switch (ct) {
17759371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
1776e5c487bfSMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1777e5c487bfSMatthew G. Knepley 
17789371c9d4SSatish Balay     for (v = 0; v < 3; ++v) {
17799371c9d4SSatish Balay       centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.;
17809371c9d4SSatish Balay       centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.;
17819371c9d4SSatish Balay     }
1782e5c487bfSMatthew G. Knepley     for (e = 0; e < 3; ++e) {
1783e5c487bfSMatthew G. Knepley       refCoords[0] = refVertices[e * 2 + 0];
1784e5c487bfSMatthew G. Knepley       refCoords[1] = refVertices[e * 2 + 1];
1785e5c487bfSMatthew G. Knepley       for (d = 1; d <= edgeDiv; ++d) {
1786e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv;
1787e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv;
1788e5c487bfSMatthew G. Knepley       }
17899566063dSJacob Faibussowitsch       PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1790e5c487bfSMatthew G. Knepley       for (d = 0; d < edgeDiv; ++d) {
17919566063dSJacob Faibussowitsch         PetscCall(PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], fillColor, fillColor, fillColor));
17929566063dSJacob Faibussowitsch         PetscCall(PetscDrawLine(draw, edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], PETSC_DRAW_BLACK));
1793e5c487bfSMatthew G. Knepley       }
1794e5c487bfSMatthew G. Knepley     }
17959371c9d4SSatish Balay   } break;
1796d71ae5a4SJacob Faibussowitsch   default:
1797d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1798e5c487bfSMatthew G. Knepley   }
17993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1800e5c487bfSMatthew G. Knepley }
1801e5c487bfSMatthew G. Knepley 
1802d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1803d71ae5a4SJacob Faibussowitsch {
1804e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1805e412dcbdSMatthew G. Knepley   DM           cdm;
1806e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1807e412dcbdSMatthew G. Knepley   Vec          coordinates;
1808c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1809e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1810e5c487bfSMatthew G. Knepley   PetscBool    isnull, drawAffine = PETSC_TRUE;
1811c9c77995SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, edgeDiv = 4;
1812e412dcbdSMatthew G. Knepley 
1813e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
18149566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
181563a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
18169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
18179566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
18189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
18199566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
18209566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
18219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1823e412dcbdSMatthew G. Knepley 
18249566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
18259566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
18263ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
18279566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1828e412dcbdSMatthew G. Knepley 
1829c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
18309566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
18319566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1832e412dcbdSMatthew G. Knepley 
1833cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1834cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1835c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1836ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1837c9c77995SMatthew G. Knepley     PetscBool          isDG;
1838cf3064d3SMatthew G. Knepley 
1839c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
18401baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
18411baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1842c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1843cf3064d3SMatthew G. Knepley   }
18449566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
18459566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
18469566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
18479566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
18483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1849e412dcbdSMatthew G. Knepley }
1850e412dcbdSMatthew G. Knepley 
1851e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm)
1852e44f6aebSMatthew G. Knepley {
1853e44f6aebSMatthew G. Knepley   DM           odm = dm, rdm = dm, cdm;
1854e44f6aebSMatthew G. Knepley   PetscFE      fe;
1855e44f6aebSMatthew G. Knepley   PetscSpace   sp;
1856e44f6aebSMatthew G. Knepley   PetscClassId id;
1857e44f6aebSMatthew G. Knepley   PetscInt     degree;
1858e44f6aebSMatthew G. Knepley   PetscBool    hoView = PETSC_TRUE;
1859e44f6aebSMatthew G. Knepley 
1860e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
1861e44f6aebSMatthew G. Knepley   PetscObjectOptionsBegin((PetscObject)dm);
1862e44f6aebSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL));
1863e44f6aebSMatthew G. Knepley   PetscOptionsEnd();
1864e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dm));
1865e44f6aebSMatthew G. Knepley   *hdm = dm;
1866e44f6aebSMatthew G. Knepley   if (!hoView) PetscFunctionReturn(PETSC_SUCCESS);
1867e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
1868e44f6aebSMatthew G. Knepley   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
1869e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1870e44f6aebSMatthew G. Knepley   if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS);
1871e44f6aebSMatthew G. Knepley   PetscCall(PetscFEGetBasisSpace(fe, &sp));
1872e44f6aebSMatthew G. Knepley   PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
1873e44f6aebSMatthew G. Knepley   for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) {
1874e44f6aebSMatthew G. Knepley     DM  cdm, rcdm;
1875e44f6aebSMatthew G. Knepley     Mat In;
1876e44f6aebSMatthew G. Knepley     Vec cl, rcl;
1877e44f6aebSMatthew G. Knepley 
1878e44f6aebSMatthew G. Knepley     PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm));
1879e44f6aebSMatthew G. Knepley     if (rd > 1) PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL));
1880e44f6aebSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates"));
1881e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(odm, &cdm));
1882e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(rdm, &rcdm));
1883e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(odm, &cl));
1884e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(rdm, &rcl));
1885e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoarseDM(rcdm, cdm));
1886e44f6aebSMatthew G. Knepley     PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL));
1887e44f6aebSMatthew G. Knepley     PetscCall(MatMult(In, cl, rcl));
1888e44f6aebSMatthew G. Knepley     PetscCall(MatDestroy(&In));
1889e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(rdm, rcl));
1890e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&odm));
1891e44f6aebSMatthew G. Knepley     odm = rdm;
1892e44f6aebSMatthew G. Knepley   }
1893e44f6aebSMatthew G. Knepley   *hdm = rdm;
1894e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1895e44f6aebSMatthew G. Knepley }
1896e44f6aebSMatthew G. Knepley 
18971e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
18981e50132fSMatthew G. Knepley   #include <exodusII.h>
18996823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
19001e50132fSMatthew G. Knepley #endif
19011e50132fSMatthew G. Knepley 
1902d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1903d71ae5a4SJacob Faibussowitsch {
19045f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1905002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1906552f7358SJed Brown 
1907552f7358SJed Brown   PetscFunctionBegin;
1908552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1909552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
19129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
19149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
19159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
19165f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1917552f7358SJed Brown   if (iascii) {
19188135c375SStefano Zampini     PetscViewerFormat format;
19199566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
19201baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
19211baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1922c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1923c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
19249566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1925c6ccd67eSMatthew G. Knepley #else
1926c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1927552f7358SJed Brown #endif
1928e412dcbdSMatthew G. Knepley   } else if (isvtk) {
19299566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1930e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1931e44f6aebSMatthew G. Knepley     DM hdm;
1932e44f6aebSMatthew G. Knepley 
1933e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm));
1934e44f6aebSMatthew G. Knepley     PetscCall(DMPlexView_Draw(hdm, viewer));
1935e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&hdm));
19368135c375SStefano Zampini   } else if (isglvis) {
19379566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
19381e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19391e50132fSMatthew G. Knepley   } else if (isexodus) {
19406823f3c5SBlaise Bourdin     /*
19416823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
19426823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1943da81f932SPierre Jolivet       with ID 1, containing all cells.
19446823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
19456823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
19466823f3c5SBlaise Bourdin     */
19476823f3c5SBlaise Bourdin     PetscInt numCS;
19489566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
19496823f3c5SBlaise Bourdin     if (!numCS) {
19501e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
19519566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
19529566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
19539566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
19546823f3c5SBlaise Bourdin     }
19559566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
19561e50132fSMatthew G. Knepley #endif
19575f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
19585f34f2dcSJed Brown   } else if (iscgns) {
19595f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
19605f34f2dcSJed Brown #endif
19611baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1962cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
19639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1964cb3ba0daSMatthew G. Knepley   if (flg) {
1965cb3ba0daSMatthew G. Knepley     Vec ranks;
19669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
19679566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
19689566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1969cb3ba0daSMatthew G. Knepley   }
1970002a2709SMatthew G. Knepley   /* Optionally view a label */
19719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1972002a2709SMatthew G. Knepley   if (flg) {
1973002a2709SMatthew G. Knepley     DMLabel label;
1974002a2709SMatthew G. Knepley     Vec     val;
1975002a2709SMatthew G. Knepley 
19769566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
197728b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
19789566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
19799566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
19809566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1981002a2709SMatthew G. Knepley   }
19823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1983552f7358SJed Brown }
1984552f7358SJed Brown 
19857f96f51bSksagiyam /*@
1986a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
19877f96f51bSksagiyam 
198820f4b53cSBarry Smith   Collective
19897f96f51bSksagiyam 
19907f96f51bSksagiyam   Input Parameters:
1991a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
1992a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
19937f96f51bSksagiyam 
19947f96f51bSksagiyam   Level: advanced
19957f96f51bSksagiyam 
19961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
19977f96f51bSksagiyam @*/
1998d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
1999d71ae5a4SJacob Faibussowitsch {
20007f96f51bSksagiyam   PetscBool ishdf5;
20017f96f51bSksagiyam 
20027f96f51bSksagiyam   PetscFunctionBegin;
20037f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20047f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
20077f96f51bSksagiyam   if (ishdf5) {
20087f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
20097f96f51bSksagiyam     PetscViewerFormat format;
20109566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20117f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20127f96f51bSksagiyam       IS globalPointNumbering;
20137f96f51bSksagiyam 
20149566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
20159566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
20169566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
201798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
20187f96f51bSksagiyam #else
20197f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20207f96f51bSksagiyam #endif
20217f96f51bSksagiyam   }
20229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
20233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20247f96f51bSksagiyam }
20257f96f51bSksagiyam 
202677b8e257Sksagiyam /*@
2027a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
202877b8e257Sksagiyam 
202920f4b53cSBarry Smith   Collective
203077b8e257Sksagiyam 
203177b8e257Sksagiyam   Input Parameters:
2032a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
2033a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
203477b8e257Sksagiyam 
203577b8e257Sksagiyam   Level: advanced
203677b8e257Sksagiyam 
20371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
203877b8e257Sksagiyam @*/
2039d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
2040d71ae5a4SJacob Faibussowitsch {
204177b8e257Sksagiyam   PetscBool ishdf5;
204277b8e257Sksagiyam 
204377b8e257Sksagiyam   PetscFunctionBegin;
204477b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
204577b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
204877b8e257Sksagiyam   if (ishdf5) {
204977b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
205077b8e257Sksagiyam     PetscViewerFormat format;
20519566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
205277b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20539566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
2054fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
205577b8e257Sksagiyam #else
205677b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
205777b8e257Sksagiyam #endif
205877b8e257Sksagiyam   }
20599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
20603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206177b8e257Sksagiyam }
206277b8e257Sksagiyam 
2063bd6565f1Sksagiyam /*@
2064a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
2065bd6565f1Sksagiyam 
206620f4b53cSBarry Smith   Collective
2067bd6565f1Sksagiyam 
2068bd6565f1Sksagiyam   Input Parameters:
2069a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
2070a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
2071bd6565f1Sksagiyam 
2072bd6565f1Sksagiyam   Level: advanced
2073bd6565f1Sksagiyam 
20741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
2075bd6565f1Sksagiyam @*/
2076d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
2077d71ae5a4SJacob Faibussowitsch {
2078bd6565f1Sksagiyam   PetscBool ishdf5;
2079bd6565f1Sksagiyam 
2080bd6565f1Sksagiyam   PetscFunctionBegin;
2081bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2082bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
2085bd6565f1Sksagiyam   if (ishdf5) {
2086bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
2087bd6565f1Sksagiyam     IS                globalPointNumbering;
2088bd6565f1Sksagiyam     PetscViewerFormat format;
2089bd6565f1Sksagiyam 
20909566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2091bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20929566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
20939566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
20949566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
209598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2096bd6565f1Sksagiyam #else
2097bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2098bd6565f1Sksagiyam #endif
2099bd6565f1Sksagiyam   }
21009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
21013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2102bd6565f1Sksagiyam }
2103bd6565f1Sksagiyam 
2104021affd3Sksagiyam /*@
2105a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
2106021affd3Sksagiyam 
210720f4b53cSBarry Smith   Collective
2108021affd3Sksagiyam 
2109021affd3Sksagiyam   Input Parameters:
2110a1cb98faSBarry Smith + dm        - The `DM` that contains the topology on which the section to be saved is defined
2111a1cb98faSBarry Smith . viewer    - The `PetscViewer` for saving
2112a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved
2113021affd3Sksagiyam 
2114021affd3Sksagiyam   Level: advanced
2115021affd3Sksagiyam 
2116021affd3Sksagiyam   Notes:
2117420bcc1bSBarry Smith   This function is a wrapper around `PetscSectionView()`; in addition to the raw section, it saves information that associates the section points to the topology (`dm`) points. When the topology (`dm`) and the section are later loaded with `DMPlexTopologyLoad()` and `DMPlexSectionLoad()`, respectively, this information is used to match section points with topology points.
2118021affd3Sksagiyam 
2119420bcc1bSBarry Smith   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2120021affd3Sksagiyam 
21211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
2122021affd3Sksagiyam @*/
2123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
2124d71ae5a4SJacob Faibussowitsch {
2125021affd3Sksagiyam   PetscBool ishdf5;
2126021affd3Sksagiyam 
2127021affd3Sksagiyam   PetscFunctionBegin;
2128021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2129021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2130021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
2133021affd3Sksagiyam   if (ishdf5) {
2134021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
21359566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
2136021affd3Sksagiyam #else
2137021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2138021affd3Sksagiyam #endif
2139021affd3Sksagiyam   }
21409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
21413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2142021affd3Sksagiyam }
2143021affd3Sksagiyam 
21443e97647fSksagiyam /*@
21453e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
21463e97647fSksagiyam 
214720f4b53cSBarry Smith   Collective
21483e97647fSksagiyam 
21493e97647fSksagiyam   Input Parameters:
2150a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2151a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
2152a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
21533e97647fSksagiyam - vec       - The global vector to be saved
21543e97647fSksagiyam 
21553e97647fSksagiyam   Level: advanced
21563e97647fSksagiyam 
21573e97647fSksagiyam   Notes:
2158420bcc1bSBarry Smith   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
21593e97647fSksagiyam 
216060225df5SJacob Faibussowitsch   Calling sequence:
2161a1cb98faSBarry Smith .vb
2162a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2163a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2164a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2165a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2166a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2167a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2168a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2169a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2170a1cb98faSBarry Smith        PetscSectionSetUp(section);
2171a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2172a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2173a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2174a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2175a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2176a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2177a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2178a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2179a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2180a1cb98faSBarry Smith        DMDestroy(&dm);
2181a1cb98faSBarry Smith .ve
21823e97647fSksagiyam 
21831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
21843e97647fSksagiyam @*/
2185d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2186d71ae5a4SJacob Faibussowitsch {
21873e97647fSksagiyam   PetscBool ishdf5;
21883e97647fSksagiyam 
21893e97647fSksagiyam   PetscFunctionBegin;
21903e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21913e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21923e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21933e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
21943e97647fSksagiyam   /* Check consistency */
21953e97647fSksagiyam   {
21963e97647fSksagiyam     PetscSection section;
21973e97647fSksagiyam     PetscBool    includesConstraints;
21983e97647fSksagiyam     PetscInt     m, m1;
21993e97647fSksagiyam 
22009566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22019566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
22029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22039566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22049566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
220563a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
22063e97647fSksagiyam   }
22079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22093e97647fSksagiyam   if (ishdf5) {
22103e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
22119566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
22123e97647fSksagiyam #else
22133e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22143e97647fSksagiyam #endif
22153e97647fSksagiyam   }
22169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22183e97647fSksagiyam }
22193e97647fSksagiyam 
22203e97647fSksagiyam /*@
22213e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
22223e97647fSksagiyam 
222320f4b53cSBarry Smith   Collective
22243e97647fSksagiyam 
22253e97647fSksagiyam   Input Parameters:
2226a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2227a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
222820f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm`
22293e97647fSksagiyam - vec       - The local vector to be saved
22303e97647fSksagiyam 
22313e97647fSksagiyam   Level: advanced
22323e97647fSksagiyam 
2233a1cb98faSBarry Smith   Note:
223420f4b53cSBarry Smith   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
22353e97647fSksagiyam 
223660225df5SJacob Faibussowitsch   Calling sequence:
2237a1cb98faSBarry Smith .vb
2238a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2239a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2240a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2241a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2242a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2243a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2244a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2245a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2246a1cb98faSBarry Smith        PetscSectionSetUp(section);
2247a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2248a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2249a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2250a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2251a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2252a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2253a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2254a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2255a1cb98faSBarry Smith        DMDestroy(&dm);
2256a1cb98faSBarry Smith .ve
22573e97647fSksagiyam 
22581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22593e97647fSksagiyam @*/
2260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2261d71ae5a4SJacob Faibussowitsch {
22623e97647fSksagiyam   PetscBool ishdf5;
22633e97647fSksagiyam 
22643e97647fSksagiyam   PetscFunctionBegin;
22653e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22663e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22673e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22683e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22693e97647fSksagiyam   /* Check consistency */
22703e97647fSksagiyam   {
22713e97647fSksagiyam     PetscSection section;
22723e97647fSksagiyam     PetscBool    includesConstraints;
22733e97647fSksagiyam     PetscInt     m, m1;
22743e97647fSksagiyam 
22759566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22769566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
22779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22789566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22799566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
228063a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
22813e97647fSksagiyam   }
22829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
22843e97647fSksagiyam   if (ishdf5) {
22853e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
22869566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
22873e97647fSksagiyam #else
22883e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22893e97647fSksagiyam #endif
22903e97647fSksagiyam   }
22919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
22923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22933e97647fSksagiyam }
22943e97647fSksagiyam 
2295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2296d71ae5a4SJacob Faibussowitsch {
2297d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
22982c40f234SMatthew G. Knepley 
22992c40f234SMatthew G. Knepley   PetscFunctionBegin;
23002c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23012c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2303d4f5a9a0SVaclav Hapla   if (ishdf5) {
23042c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
23059c48423bSVaclav Hapla     PetscViewerFormat format;
23069566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23079c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
23089566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2309509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23109566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
231198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
23123ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23132c40f234SMatthew G. Knepley #else
23142c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2315552f7358SJed Brown #endif
231698921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2317552f7358SJed Brown }
2318552f7358SJed Brown 
2319ea8e1828Sksagiyam /*@
2320a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2321ea8e1828Sksagiyam 
232220f4b53cSBarry Smith   Collective
2323ea8e1828Sksagiyam 
2324ea8e1828Sksagiyam   Input Parameters:
2325a1cb98faSBarry Smith + dm     - The `DM` into which the topology is loaded
2326a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology
2327ea8e1828Sksagiyam 
23282fe279fdSBarry Smith   Output Parameter:
232920f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded
2330dec9e869Sksagiyam 
2331ea8e1828Sksagiyam   Level: advanced
2332ea8e1828Sksagiyam 
23331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2334a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2335ea8e1828Sksagiyam @*/
2336d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2337d71ae5a4SJacob Faibussowitsch {
2338ea8e1828Sksagiyam   PetscBool ishdf5;
2339ea8e1828Sksagiyam 
2340ea8e1828Sksagiyam   PetscFunctionBegin;
2341ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2342ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23434f572ea9SToby Isaac   if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3);
23449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2346ea8e1828Sksagiyam   if (ishdf5) {
2347ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2348ea8e1828Sksagiyam     PetscViewerFormat format;
23499566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2350ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23519566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
235298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2353ea8e1828Sksagiyam #else
2354ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2355ea8e1828Sksagiyam #endif
2356ea8e1828Sksagiyam   }
23579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
23583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2359ea8e1828Sksagiyam }
2360ea8e1828Sksagiyam 
23613e701f1cSksagiyam /*@
2362a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
23633e701f1cSksagiyam 
236420f4b53cSBarry Smith   Collective
23653e701f1cSksagiyam 
23663e701f1cSksagiyam   Input Parameters:
2367a1cb98faSBarry Smith + dm                   - The `DM` into which the coordinates are loaded
2368a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved coordinates
2369a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
23703e701f1cSksagiyam 
23713e701f1cSksagiyam   Level: advanced
23723e701f1cSksagiyam 
23731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2374a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
23753e701f1cSksagiyam @*/
2376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2377d71ae5a4SJacob Faibussowitsch {
23783e701f1cSksagiyam   PetscBool ishdf5;
23793e701f1cSksagiyam 
23803e701f1cSksagiyam   PetscFunctionBegin;
23813e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23823e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2383c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
23849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
23863e701f1cSksagiyam   if (ishdf5) {
23873e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
23883e701f1cSksagiyam     PetscViewerFormat format;
23899566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23903e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23919566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
239298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
23933e701f1cSksagiyam #else
23943e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23953e701f1cSksagiyam #endif
23963e701f1cSksagiyam   }
23979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
23983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23993e701f1cSksagiyam }
24003e701f1cSksagiyam 
2401b08ad5deSksagiyam /*@
2402a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2403b08ad5deSksagiyam 
240420f4b53cSBarry Smith   Collective
2405b08ad5deSksagiyam 
2406b08ad5deSksagiyam   Input Parameters:
2407a1cb98faSBarry Smith + dm                   - The `DM` into which the labels are loaded
2408a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved labels
240920f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2410b08ad5deSksagiyam 
2411b08ad5deSksagiyam   Level: advanced
2412b08ad5deSksagiyam 
2413a1cb98faSBarry Smith   Note:
2414a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2415e6368b79SVaclav Hapla 
24161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2417a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2418b08ad5deSksagiyam @*/
2419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2420d71ae5a4SJacob Faibussowitsch {
2421b08ad5deSksagiyam   PetscBool ishdf5;
2422b08ad5deSksagiyam 
2423b08ad5deSksagiyam   PetscFunctionBegin;
2424b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2425b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2426e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2429b08ad5deSksagiyam   if (ishdf5) {
2430b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2431b08ad5deSksagiyam     PetscViewerFormat format;
2432b08ad5deSksagiyam 
24339566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2434b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24359566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
243698921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2437b08ad5deSksagiyam #else
2438b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2439b08ad5deSksagiyam #endif
2440b08ad5deSksagiyam   }
24419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
24423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2443b08ad5deSksagiyam }
2444b08ad5deSksagiyam 
2445f84dd6b4Sksagiyam /*@
2446a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2447f84dd6b4Sksagiyam 
244820f4b53cSBarry Smith   Collective
2449f84dd6b4Sksagiyam 
2450f84dd6b4Sksagiyam   Input Parameters:
2451a1cb98faSBarry Smith + dm                   - The `DM` that represents the topology
2452a1cb98faSBarry Smith . viewer               - The `PetscViewer` that represents the on-disk section (sectionA)
2453a1cb98faSBarry Smith . sectiondm            - The `DM` into which the on-disk section (sectionA) is migrated
2454a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2455f84dd6b4Sksagiyam 
2456a4e35b19SJacob Faibussowitsch   Output Parameters:
245720f4b53cSBarry Smith + globalDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a global `Vec` associated with the `sectiondm`'s global section (`NULL` if not needed)
245820f4b53cSBarry Smith - localDofSF  - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a local `Vec` associated with the `sectiondm`'s local section (`NULL` if not needed)
2459f84dd6b4Sksagiyam 
2460f84dd6b4Sksagiyam   Level: advanced
2461f84dd6b4Sksagiyam 
2462f84dd6b4Sksagiyam   Notes:
246320f4b53cSBarry Smith   This function is a wrapper around `PetscSectionLoad()`; it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in `dm`. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points.
2464f84dd6b4Sksagiyam 
246520f4b53cSBarry Smith   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2466f84dd6b4Sksagiyam 
246720f4b53cSBarry Smith   The output parameter, `globalDofSF` (`localDofSF`), can later be used with `DMPlexGlobalVectorLoad()` (`DMPlexLocalVectorLoad()`) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section.
2468f84dd6b4Sksagiyam 
2469f84dd6b4Sksagiyam   Example using 2 processes:
2470a1cb98faSBarry Smith .vb
2471a1cb98faSBarry Smith   NX (number of points on dm): 4
2472a1cb98faSBarry Smith   sectionA                   : the on-disk section
2473a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2474a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2475a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2476a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2477f84dd6b4Sksagiyam 
2478a1cb98faSBarry Smith                                      rank 0    rank 1
2479a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2480a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2481a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2482a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2483a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2484a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2485a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2486a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2487a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2488a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2489a1cb98faSBarry Smith .ve
2490a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2491a1cb98faSBarry Smith 
24921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2493f84dd6b4Sksagiyam @*/
2494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2495d71ae5a4SJacob Faibussowitsch {
2496f84dd6b4Sksagiyam   PetscBool ishdf5;
2497f84dd6b4Sksagiyam 
2498f84dd6b4Sksagiyam   PetscFunctionBegin;
2499f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2500f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2501f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2502f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
25034f572ea9SToby Isaac   if (globalDofSF) PetscAssertPointer(globalDofSF, 5);
25044f572ea9SToby Isaac   if (localDofSF) PetscAssertPointer(localDofSF, 6);
25059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2507f84dd6b4Sksagiyam   if (ishdf5) {
2508f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
25099566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2510f84dd6b4Sksagiyam #else
2511f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2512f84dd6b4Sksagiyam #endif
2513f84dd6b4Sksagiyam   }
25149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
25153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2516f84dd6b4Sksagiyam }
2517f84dd6b4Sksagiyam 
25188be3dfe1Sksagiyam /*@
25198be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
25208be3dfe1Sksagiyam 
252120f4b53cSBarry Smith   Collective
25228be3dfe1Sksagiyam 
25238be3dfe1Sksagiyam   Input Parameters:
2524a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2525a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2526a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
2527a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
25288be3dfe1Sksagiyam - vec       - The global vector to set values of
25298be3dfe1Sksagiyam 
25308be3dfe1Sksagiyam   Level: advanced
25318be3dfe1Sksagiyam 
25328be3dfe1Sksagiyam   Notes:
2533a1cb98faSBarry Smith   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
25348be3dfe1Sksagiyam 
253560225df5SJacob Faibussowitsch   Calling sequence:
2536a1cb98faSBarry Smith .vb
2537a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2538a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2539a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2540a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2541a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2542a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2543a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2544a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2545a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2546a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2547a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2548a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2549a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2550a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2551a1cb98faSBarry Smith        DMDestroy(&dm);
2552a1cb98faSBarry Smith .ve
25538be3dfe1Sksagiyam 
25541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2555a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
25568be3dfe1Sksagiyam @*/
2557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2558d71ae5a4SJacob Faibussowitsch {
25598be3dfe1Sksagiyam   PetscBool ishdf5;
25608be3dfe1Sksagiyam 
25618be3dfe1Sksagiyam   PetscFunctionBegin;
25628be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25638be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25648be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
25658be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
25668be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
25678be3dfe1Sksagiyam   /* Check consistency */
25688be3dfe1Sksagiyam   {
25698be3dfe1Sksagiyam     PetscSection section;
25708be3dfe1Sksagiyam     PetscBool    includesConstraints;
25718be3dfe1Sksagiyam     PetscInt     m, m1;
25728be3dfe1Sksagiyam 
25739566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25749566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
25759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25769566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25779566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
257863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
25798be3dfe1Sksagiyam   }
25809566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
25828be3dfe1Sksagiyam   if (ishdf5) {
25838be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
25849566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
25858be3dfe1Sksagiyam #else
25868be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
25878be3dfe1Sksagiyam #endif
25888be3dfe1Sksagiyam   }
25899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
25903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25918be3dfe1Sksagiyam }
25928be3dfe1Sksagiyam 
25938be3dfe1Sksagiyam /*@
25948be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
25958be3dfe1Sksagiyam 
259620f4b53cSBarry Smith   Collective
25978be3dfe1Sksagiyam 
25988be3dfe1Sksagiyam   Input Parameters:
2599a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2600a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2601a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined
2602a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
26038be3dfe1Sksagiyam - vec       - The local vector to set values of
26048be3dfe1Sksagiyam 
26058be3dfe1Sksagiyam   Level: advanced
26068be3dfe1Sksagiyam 
26078be3dfe1Sksagiyam   Notes:
260820f4b53cSBarry Smith   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
26098be3dfe1Sksagiyam 
261060225df5SJacob Faibussowitsch   Calling sequence:
2611a1cb98faSBarry Smith .vb
2612a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2613a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2614a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2615a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2616a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2617a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2618a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2619a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2620a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2621a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2622a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2623a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2624a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2625a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2626a1cb98faSBarry Smith        DMDestroy(&dm);
2627a1cb98faSBarry Smith .ve
26288be3dfe1Sksagiyam 
26291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2630a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
26318be3dfe1Sksagiyam @*/
2632d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2633d71ae5a4SJacob Faibussowitsch {
26348be3dfe1Sksagiyam   PetscBool ishdf5;
26358be3dfe1Sksagiyam 
26368be3dfe1Sksagiyam   PetscFunctionBegin;
26378be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26388be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
26398be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
26408be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
26418be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
26428be3dfe1Sksagiyam   /* Check consistency */
26438be3dfe1Sksagiyam   {
26448be3dfe1Sksagiyam     PetscSection section;
26458be3dfe1Sksagiyam     PetscBool    includesConstraints;
26468be3dfe1Sksagiyam     PetscInt     m, m1;
26478be3dfe1Sksagiyam 
26489566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
26499566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
26509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
26519566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
26529566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
265363a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
26548be3dfe1Sksagiyam   }
26559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26578be3dfe1Sksagiyam   if (ishdf5) {
26588be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26599566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26608be3dfe1Sksagiyam #else
26618be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26628be3dfe1Sksagiyam #endif
26638be3dfe1Sksagiyam   }
26649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26668be3dfe1Sksagiyam }
26678be3dfe1Sksagiyam 
2668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2669d71ae5a4SJacob Faibussowitsch {
2670552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2671552f7358SJed Brown 
2672552f7358SJed Brown   PetscFunctionBegin;
26739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
26749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
26759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
26769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
26776c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL));
26782e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
26792e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
26802e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
26812e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
26826bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
26836bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2684c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2685c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
2686d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL));
2687d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL));
26885f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
26893ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
26909566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
26919566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
26929566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
26939566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
26949566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
26959566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
269621027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
26979f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
26989566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
26999566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
27009566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
27011d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
27029566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
27039566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
27049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
27059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
27069566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
27074e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
27086725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
27096725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
27109566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
27119566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
27129566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
27139566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
27149566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
27159566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
27169566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
27179566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
27189566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
27199566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
27209566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2721552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
27229566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
27233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2724552f7358SJed Brown }
2725552f7358SJed Brown 
2726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2727d71ae5a4SJacob Faibussowitsch {
27288d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2729acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
27309fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2731837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2732b412c318SBarry Smith   MatType                mtype;
27331428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2734552f7358SJed Brown 
2735552f7358SJed Brown   PetscFunctionBegin;
27369566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2737b412c318SBarry Smith   mtype = dm->mattype;
27389566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
27399566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
27409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
27419fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
27429566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
27439566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
27449566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
27459566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
27469566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2747acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
27489566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
27499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
27509566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
27519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
27529566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
27539566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
27549566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
27559566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2756552f7358SJed Brown   if (!isShell) {
2757837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
27589fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2759863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2760552f7358SJed Brown 
27619566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
27629fca9976SJed Brown 
27639fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
27649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2765863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2766e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2767863027abSJed Brown       switch (dm->blocking_type) {
27680e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
27699fca9976SJed Brown         PetscInt bdof, offset;
2770a9d99c84SMatthew G. Knepley 
27719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
27729fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
27739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
27749371c9d4SSatish Balay         for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof;
27751d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
27761d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
27771d17a0a3SMatthew G. Knepley         if (dof) {
27789371c9d4SSatish Balay           if (bs < 0) {
27799371c9d4SSatish Balay             bs = bdof;
27809371c9d4SSatish Balay           } else if (bs != bdof) {
27819371c9d4SSatish Balay             bs = 1;
27829371c9d4SSatish Balay           }
2783552f7358SJed Brown         }
2784863027abSJed Brown       } break;
2785863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2786863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2787863027abSJed Brown           PetscInt num_comp, bdof, offset;
2788863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2789863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2790863027abSJed Brown           if (dof < 0) continue;
2791863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2792863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2793863027abSJed Brown           PetscAssert(dof % num_comp == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " field %" PetscInt_FMT " has %" PetscInt_FMT " dof, not divisible by %" PetscInt_FMT " component ", p, field, dof, num_comp);
2794863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2795863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2796863027abSJed Brown           // Handle possibly constant block size (unlikely)
2797863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2798863027abSJed Brown           if (dof) {
2799863027abSJed Brown             if (bs < 0) {
2800863027abSJed Brown               bs = bdof;
2801863027abSJed Brown             } else if (bs != bdof) {
2802863027abSJed Brown               bs = 1;
2803863027abSJed Brown             }
2804863027abSJed Brown           }
2805863027abSJed Brown         }
2806863027abSJed Brown       } break;
2807863027abSJed Brown       }
28082a28c762SMatthew G Knepley     }
28092a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2810e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2811e432b41dSStefano Zampini     bsLocal[1] = bs;
28129566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2813e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2814e432b41dSStefano Zampini     else bs = bsMinMax[0];
28156fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
28169566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
28170682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
28189566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
28199566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
28200682b8bbSJed Brown     } else {
28219566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
28229566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
28239566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2824552f7358SJed Brown     }
28259fca9976SJed Brown     { // Consolidate blocks
28269fca9976SJed Brown       PetscInt nblocks = 0;
28279fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
28289fca9976SJed Brown         if (pblocks[i] == 0) continue;
28299fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2830ad540459SPierre Jolivet         for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]);
28319fca9976SJed Brown       }
28329fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
28339fca9976SJed Brown     }
28349fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2835aa0f6e3cSJed Brown   }
28369566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
28373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2838552f7358SJed Brown }
2839552f7358SJed Brown 
28407cd05799SMatthew G. Knepley /*@
2841a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2842be36d101SStefano Zampini 
2843a1cb98faSBarry Smith   Not Collective
2844be36d101SStefano Zampini 
2845be36d101SStefano Zampini   Input Parameter:
284660225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2847be36d101SStefano Zampini 
28482fe279fdSBarry Smith   Output Parameter:
2849be36d101SStefano Zampini . subsection - The subdomain section
2850be36d101SStefano Zampini 
2851be36d101SStefano Zampini   Level: developer
2852be36d101SStefano Zampini 
28531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
28547cd05799SMatthew G. Knepley @*/
2855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2856d71ae5a4SJacob Faibussowitsch {
2857be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2858be36d101SStefano Zampini 
2859be36d101SStefano Zampini   PetscFunctionBegin;
2860be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2861be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2862be36d101SStefano Zampini     PetscSection section;
2863be36d101SStefano Zampini     PetscSF      sf;
2864be36d101SStefano Zampini 
28659566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
28669566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
28679566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
28689566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2869be36d101SStefano Zampini   }
2870be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
28713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2872be36d101SStefano Zampini }
2873be36d101SStefano Zampini 
2874552f7358SJed Brown /*@
287520f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2876552f7358SJed Brown 
2877a1cb98faSBarry Smith   Not Collective
2878552f7358SJed Brown 
2879552f7358SJed Brown   Input Parameter:
288060225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2881552f7358SJed Brown 
2882552f7358SJed Brown   Output Parameters:
2883552f7358SJed Brown + pStart - The first mesh point
2884552f7358SJed Brown - pEnd   - The upper bound for mesh points
2885552f7358SJed Brown 
2886552f7358SJed Brown   Level: beginner
2887552f7358SJed Brown 
28881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2889552f7358SJed Brown @*/
2890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2891d71ae5a4SJacob Faibussowitsch {
2892552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2893552f7358SJed Brown 
2894552f7358SJed Brown   PetscFunctionBegin;
2895552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28969f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
28979f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
28983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2899552f7358SJed Brown }
2900552f7358SJed Brown 
2901552f7358SJed Brown /*@
290220f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2903552f7358SJed Brown 
2904a1cb98faSBarry Smith   Not Collective
2905552f7358SJed Brown 
2906552f7358SJed Brown   Input Parameters:
290760225df5SJacob Faibussowitsch + dm     - The `DMPLEX`
2908552f7358SJed Brown . pStart - The first mesh point
2909552f7358SJed Brown - pEnd   - The upper bound for mesh points
2910552f7358SJed Brown 
2911552f7358SJed Brown   Level: beginner
2912552f7358SJed Brown 
29131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2914552f7358SJed Brown @*/
2915d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2916d71ae5a4SJacob Faibussowitsch {
2917552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2918552f7358SJed Brown 
2919552f7358SJed Brown   PetscFunctionBegin;
2920552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29219566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
29229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
292321027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
29243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2925552f7358SJed Brown }
2926552f7358SJed Brown 
2927552f7358SJed Brown /*@
2928eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2929552f7358SJed Brown 
2930a1cb98faSBarry Smith   Not Collective
2931552f7358SJed Brown 
2932552f7358SJed Brown   Input Parameters:
293360225df5SJacob Faibussowitsch + dm - The `DMPLEX`
2934a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2935552f7358SJed Brown 
2936552f7358SJed Brown   Output Parameter:
293720f4b53cSBarry Smith . size - The cone size for point `p`
2938552f7358SJed Brown 
2939552f7358SJed Brown   Level: beginner
2940552f7358SJed Brown 
29411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2942552f7358SJed Brown @*/
2943d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2944d71ae5a4SJacob Faibussowitsch {
2945552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2946552f7358SJed Brown 
2947552f7358SJed Brown   PetscFunctionBegin;
2948552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29494f572ea9SToby Isaac   PetscAssertPointer(size, 3);
29509f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
29519f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
29523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2953552f7358SJed Brown }
2954552f7358SJed Brown 
2955552f7358SJed Brown /*@
2956eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2957552f7358SJed Brown 
2958a1cb98faSBarry Smith   Not Collective
2959552f7358SJed Brown 
2960552f7358SJed Brown   Input Parameters:
296160225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
2962a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
296320f4b53cSBarry Smith - size - The cone size for point `p`
2964552f7358SJed Brown 
2965552f7358SJed Brown   Level: beginner
2966552f7358SJed Brown 
2967a1cb98faSBarry Smith   Note:
2968a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
2969a1cb98faSBarry Smith 
29701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2971552f7358SJed Brown @*/
2972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2973d71ae5a4SJacob Faibussowitsch {
2974552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2975552f7358SJed Brown 
2976552f7358SJed Brown   PetscFunctionBegin;
2977552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29789f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
29799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
29803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2981552f7358SJed Brown }
2982552f7358SJed Brown 
2983552f7358SJed Brown /*@C
2984eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2985552f7358SJed Brown 
2986a1cb98faSBarry Smith   Not Collective
2987552f7358SJed Brown 
2988552f7358SJed Brown   Input Parameters:
2989a1cb98faSBarry Smith + dm - The `DMPLEX`
2990a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2991552f7358SJed Brown 
2992552f7358SJed Brown   Output Parameter:
299320f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
2994552f7358SJed Brown 
2995552f7358SJed Brown   Level: beginner
2996552f7358SJed Brown 
299760225df5SJacob Faibussowitsch   Fortran Notes:
2998a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
2999a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
30003813dfbdSMatthew G Knepley 
30011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
3002552f7358SJed Brown @*/
3003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
3004d71ae5a4SJacob Faibussowitsch {
3005552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3006552f7358SJed Brown   PetscInt off;
3007552f7358SJed Brown 
3008552f7358SJed Brown   PetscFunctionBegin;
3009552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30104f572ea9SToby Isaac   PetscAssertPointer(cone, 3);
30119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3012552f7358SJed Brown   *cone = &mesh->cones[off];
30133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3014552f7358SJed Brown }
3015552f7358SJed Brown 
30160ce7577fSVaclav Hapla /*@C
30170ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
30180ce7577fSVaclav Hapla 
3019a1cb98faSBarry Smith   Not Collective
30200ce7577fSVaclav Hapla 
30210ce7577fSVaclav Hapla   Input Parameters:
3022a1cb98faSBarry Smith + dm - The `DMPLEX`
3023a1cb98faSBarry Smith - p  - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
30240ce7577fSVaclav Hapla 
3025d8d19677SJose E. Roman   Output Parameters:
302620f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
302720f4b53cSBarry Smith - pCones        - An array of points which are on the in-edges for the point set `p`
30280ce7577fSVaclav Hapla 
30290ce7577fSVaclav Hapla   Level: intermediate
30300ce7577fSVaclav Hapla 
30311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
30320ce7577fSVaclav Hapla @*/
3033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
3034d71ae5a4SJacob Faibussowitsch {
30350ce7577fSVaclav Hapla   PetscSection cs, newcs;
30360ce7577fSVaclav Hapla   PetscInt    *cones;
30370ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
30380ce7577fSVaclav Hapla   PetscInt     n;
30390ce7577fSVaclav Hapla 
30400ce7577fSVaclav Hapla   PetscFunctionBegin;
30419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
30429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
30439566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
30440ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
30450ce7577fSVaclav Hapla   if (pCones) {
30469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
30479566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
30480ce7577fSVaclav Hapla   }
30493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30500ce7577fSVaclav Hapla }
30510ce7577fSVaclav Hapla 
3052af9eab45SVaclav Hapla /*@
3053af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
3054d4636a37SVaclav Hapla 
3055a1cb98faSBarry Smith   Not Collective
3056d4636a37SVaclav Hapla 
3057d4636a37SVaclav Hapla   Input Parameters:
3058a1cb98faSBarry Smith + dm     - The `DMPLEX`
3059a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3060d4636a37SVaclav Hapla 
3061d4636a37SVaclav Hapla   Output Parameter:
3062af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
3063d4636a37SVaclav Hapla 
3064d4636a37SVaclav Hapla   Level: advanced
3065d4636a37SVaclav Hapla 
3066af9eab45SVaclav Hapla   Notes:
306720f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
3068af9eab45SVaclav Hapla 
3069a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
3070a1cb98faSBarry Smith 
30711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
3072a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
3073d4636a37SVaclav Hapla @*/
3074d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
3075d71ae5a4SJacob Faibussowitsch {
3076af9eab45SVaclav Hapla   IS      *expandedPointsAll;
3077af9eab45SVaclav Hapla   PetscInt depth;
3078d4636a37SVaclav Hapla 
3079d4636a37SVaclav Hapla   PetscFunctionBegin;
3080af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3081af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
30824f572ea9SToby Isaac   PetscAssertPointer(expandedPoints, 3);
30839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
3084af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
30859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
30869566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
30873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3088af9eab45SVaclav Hapla }
3089af9eab45SVaclav Hapla 
3090af9eab45SVaclav Hapla /*@
3091af9eab45SVaclav 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).
3092af9eab45SVaclav Hapla 
3093a1cb98faSBarry Smith   Not Collective
3094af9eab45SVaclav Hapla 
3095af9eab45SVaclav Hapla   Input Parameters:
3096a1cb98faSBarry Smith + dm     - The `DMPLEX`
3097a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3098af9eab45SVaclav Hapla 
3099d8d19677SJose E. Roman   Output Parameters:
3100a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3101af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
3102af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3103af9eab45SVaclav Hapla 
3104af9eab45SVaclav Hapla   Level: advanced
3105af9eab45SVaclav Hapla 
3106af9eab45SVaclav Hapla   Notes:
3107a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
3108af9eab45SVaclav Hapla 
3109a4e35b19SJacob Faibussowitsch   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.
3110af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
3111af9eab45SVaclav Hapla 
3112a4e35b19SJacob Faibussowitsch   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\:
3113a4e35b19SJacob Faibussowitsch   (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
3114a4e35b19SJacob Faibussowitsch   (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
3115af9eab45SVaclav Hapla 
31161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3117a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
3118af9eab45SVaclav Hapla @*/
3119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3120d71ae5a4SJacob Faibussowitsch {
3121af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
3122af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
3123af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
3124af9eab45SVaclav Hapla   IS             *expandedPoints_;
3125af9eab45SVaclav Hapla   PetscSection   *sections_;
3126af9eab45SVaclav Hapla 
3127af9eab45SVaclav Hapla   PetscFunctionBegin;
3128af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3129af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31304f572ea9SToby Isaac   if (depth) PetscAssertPointer(depth, 3);
31314f572ea9SToby Isaac   if (expandedPoints) PetscAssertPointer(expandedPoints, 4);
31324f572ea9SToby Isaac   if (sections) PetscAssertPointer(sections, 5);
31339566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
31349566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
31359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
31369566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
31379566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
3138af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
3139af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
31409566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
31419566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
3142af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
3144af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
31459566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
31469566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
3147af9eab45SVaclav Hapla       } else {
31489566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
3149af9eab45SVaclav Hapla       }
3150af9eab45SVaclav Hapla     }
31519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
31529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
31539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
3154af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
31569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
3157af9eab45SVaclav Hapla       if (cn > 1) {
31589566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
31599566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3160af9eab45SVaclav Hapla       } else {
3161af9eab45SVaclav Hapla         newarr[co] = arr[i];
3162af9eab45SVaclav Hapla       }
3163af9eab45SVaclav Hapla     }
31649566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3165af9eab45SVaclav Hapla     arr = newarr;
3166af9eab45SVaclav Hapla     n   = newn;
3167af9eab45SVaclav Hapla   }
31689566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3169af9eab45SVaclav Hapla   *depth = depth_;
3170af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3171af9eab45SVaclav Hapla   else {
31729566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
31739566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3174af9eab45SVaclav Hapla   }
3175af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3176af9eab45SVaclav Hapla   else {
31779566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
31789566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3179af9eab45SVaclav Hapla   }
31803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3181af9eab45SVaclav Hapla }
3182af9eab45SVaclav Hapla 
3183af9eab45SVaclav Hapla /*@
3184a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3185af9eab45SVaclav Hapla 
3186a1cb98faSBarry Smith   Not Collective
3187af9eab45SVaclav Hapla 
3188af9eab45SVaclav Hapla   Input Parameters:
3189a1cb98faSBarry Smith + dm     - The `DMPLEX`
3190a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3191af9eab45SVaclav Hapla 
3192d8d19677SJose E. Roman   Output Parameters:
3193a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3194af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3195af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3196af9eab45SVaclav Hapla 
3197af9eab45SVaclav Hapla   Level: advanced
3198af9eab45SVaclav Hapla 
3199a1cb98faSBarry Smith   Note:
3200a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3201af9eab45SVaclav Hapla 
32021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3203a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3204af9eab45SVaclav Hapla @*/
3205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3206d71ae5a4SJacob Faibussowitsch {
3207af9eab45SVaclav Hapla   PetscInt d, depth_;
3208af9eab45SVaclav Hapla 
3209af9eab45SVaclav Hapla   PetscFunctionBegin;
32109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
32111dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3212af9eab45SVaclav Hapla   if (depth) *depth = 0;
3213af9eab45SVaclav Hapla   if (expandedPoints) {
32149566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
32159566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3216af9eab45SVaclav Hapla   }
3217af9eab45SVaclav Hapla   if (sections) {
32189566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
32199566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3220af9eab45SVaclav Hapla   }
32213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3222d4636a37SVaclav Hapla }
3223d4636a37SVaclav Hapla 
3224552f7358SJed Brown /*@
322592371b87SBarry 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
3226552f7358SJed Brown 
3227a1cb98faSBarry Smith   Not Collective
3228552f7358SJed Brown 
3229552f7358SJed Brown   Input Parameters:
323060225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3231a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
323220f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3233552f7358SJed Brown 
3234552f7358SJed Brown   Level: beginner
3235552f7358SJed Brown 
3236a1cb98faSBarry Smith   Note:
3237a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3238a1cb98faSBarry Smith 
32391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3240552f7358SJed Brown @*/
3241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3242d71ae5a4SJacob Faibussowitsch {
3243552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3244552f7358SJed Brown   PetscInt dof, off, c;
3245552f7358SJed Brown 
3246552f7358SJed Brown   PetscFunctionBegin;
3247552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32494f572ea9SToby Isaac   if (dof) PetscAssertPointer(cone, 3);
32509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3251db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3252db485b19SStefano Zampini     PetscInt pStart, pEnd;
3253db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
325463a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3255552f7358SJed Brown     for (c = 0; c < dof; ++c) {
325663a3b9bcSJacob Faibussowitsch       PetscCheck(!(cone[c] < pStart) && !(cone[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cone[c], pStart, pEnd);
3257552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3258552f7358SJed Brown     }
3259db485b19SStefano Zampini   } else {
3260db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3261db485b19SStefano Zampini   }
32623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3263552f7358SJed Brown }
3264552f7358SJed Brown 
3265552f7358SJed Brown /*@C
3266eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3267552f7358SJed Brown 
3268a1cb98faSBarry Smith   Not Collective
3269552f7358SJed Brown 
3270552f7358SJed Brown   Input Parameters:
327160225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3272a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3273552f7358SJed Brown 
3274552f7358SJed Brown   Output Parameter:
327520f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3276b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3277552f7358SJed Brown 
3278552f7358SJed Brown   Level: beginner
3279552f7358SJed Brown 
3280a1cb98faSBarry Smith   Note:
3281b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3282b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3283a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3284b5a892a1SMatthew G. Knepley   with the identity.
3285b5a892a1SMatthew G. Knepley 
328660225df5SJacob Faibussowitsch   Fortran Notes:
3287a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3288a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
32893813dfbdSMatthew G Knepley 
32901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3291552f7358SJed Brown @*/
3292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3293d71ae5a4SJacob Faibussowitsch {
3294552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3295552f7358SJed Brown   PetscInt off;
3296552f7358SJed Brown 
3297552f7358SJed Brown   PetscFunctionBegin;
3298552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
329976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3300552f7358SJed Brown     PetscInt dof;
33019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33024f572ea9SToby Isaac     if (dof) PetscAssertPointer(coneOrientation, 3);
3303552f7358SJed Brown   }
33049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33050d644c17SKarl Rupp 
3306552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
33073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3308552f7358SJed Brown }
3309552f7358SJed Brown 
3310552f7358SJed Brown /*@
3311eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3312552f7358SJed Brown 
3313a1cb98faSBarry Smith   Not Collective
3314552f7358SJed Brown 
3315552f7358SJed Brown   Input Parameters:
331660225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3317a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
3318b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3319b5a892a1SMatthew G. Knepley 
3320552f7358SJed Brown   Level: beginner
3321552f7358SJed Brown 
3322a1cb98faSBarry Smith   Notes:
3323a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3324a1cb98faSBarry Smith 
3325a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3326a1cb98faSBarry Smith 
33271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3328552f7358SJed Brown @*/
3329d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3330d71ae5a4SJacob Faibussowitsch {
3331552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3332552f7358SJed Brown   PetscInt pStart, pEnd;
3333552f7358SJed Brown   PetscInt dof, off, c;
3334552f7358SJed Brown 
3335552f7358SJed Brown   PetscFunctionBegin;
3336552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33384f572ea9SToby Isaac   if (dof) PetscAssertPointer(coneOrientation, 3);
33399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3340db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3341db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
334263a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3343552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3344552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3345552f7358SJed Brown 
33469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
33471dca8a05SBarry Smith       PetscCheck(!o || (o >= -(cdof + 1) && o < cdof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ". %" PetscInt_FMT ")", o, -(cdof + 1), cdof);
3348552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3349552f7358SJed Brown     }
3350db485b19SStefano Zampini   } else {
3351db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3352db485b19SStefano Zampini   }
33533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3354552f7358SJed Brown }
3355552f7358SJed Brown 
33567cd05799SMatthew G. Knepley /*@
3357eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
33587cd05799SMatthew G. Knepley 
3359a1cb98faSBarry Smith   Not Collective
33607cd05799SMatthew G. Knepley 
33617cd05799SMatthew G. Knepley   Input Parameters:
336260225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
3363a1cb98faSBarry Smith . p         - The point, which must lie in the chart set with `DMPlexSetChart()`
33647cd05799SMatthew G. Knepley . conePos   - The local index in the cone where the point should be put
33657cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
33667cd05799SMatthew G. Knepley 
33677cd05799SMatthew G. Knepley   Level: beginner
33687cd05799SMatthew G. Knepley 
33691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
33707cd05799SMatthew G. Knepley @*/
3371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3372d71ae5a4SJacob Faibussowitsch {
3373552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3374552f7358SJed Brown   PetscInt pStart, pEnd;
3375552f7358SJed Brown   PetscInt dof, off;
3376552f7358SJed Brown 
3377552f7358SJed Brown   PetscFunctionBegin;
3378552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3379a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
33809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
338163a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
338263a3b9bcSJacob Faibussowitsch     PetscCheck(!(conePoint < pStart) && !(conePoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", conePoint, pStart, pEnd);
33839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
338463a3b9bcSJacob Faibussowitsch     PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
3385a03d55ffSStefano Zampini   }
3386a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3387552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
33883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3389552f7358SJed Brown }
3390552f7358SJed Brown 
33917cd05799SMatthew G. Knepley /*@
3392eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
33937cd05799SMatthew G. Knepley 
3394a1cb98faSBarry Smith   Not Collective
33957cd05799SMatthew G. Knepley 
33967cd05799SMatthew G. Knepley   Input Parameters:
339760225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3398a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
33997cd05799SMatthew G. Knepley . conePos         - The local index in the cone where the point should be put
34007cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
34017cd05799SMatthew G. Knepley 
34027cd05799SMatthew G. Knepley   Level: beginner
34037cd05799SMatthew G. Knepley 
3404a1cb98faSBarry Smith   Note:
3405a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3406b5a892a1SMatthew G. Knepley 
34071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34087cd05799SMatthew G. Knepley @*/
3409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3410d71ae5a4SJacob Faibussowitsch {
341177c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
341277c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
341377c88f5bSMatthew G Knepley   PetscInt dof, off;
341477c88f5bSMatthew G Knepley 
341577c88f5bSMatthew G Knepley   PetscFunctionBegin;
341677c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3417a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
341963a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
34209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
342163a3b9bcSJacob Faibussowitsch     PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
3422a03d55ffSStefano Zampini   }
3423a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
342477c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
34253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
342677c88f5bSMatthew G Knepley }
342777c88f5bSMatthew G Knepley 
34289f4ada15SMatthew G. Knepley /*@C
34299f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
34309f4ada15SMatthew G. Knepley 
34319f4ada15SMatthew G. Knepley   Not collective
34329f4ada15SMatthew G. Knepley 
34339f4ada15SMatthew G. Knepley   Input Parameters:
34349f4ada15SMatthew G. Knepley + dm - The DMPlex
34359f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
34369f4ada15SMatthew G. Knepley 
34379f4ada15SMatthew G. Knepley   Output Parameters:
343820f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
343920f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
34409f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
34419f4ada15SMatthew G. Knepley 
34429f4ada15SMatthew G. Knepley   Level: beginner
34439f4ada15SMatthew G. Knepley 
34449f4ada15SMatthew G. Knepley   Notes:
34459f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
34469f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
344720f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
34489f4ada15SMatthew G. Knepley   with the identity.
34499f4ada15SMatthew G. Knepley 
34509f4ada15SMatthew G. Knepley   Fortran Notes:
345120f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
345220f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
34539f4ada15SMatthew G. Knepley 
34541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
34559f4ada15SMatthew G. Knepley @*/
34569f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
34579f4ada15SMatthew G. Knepley {
34589f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
34599f4ada15SMatthew G. Knepley 
34609f4ada15SMatthew G. Knepley   PetscFunctionBegin;
34619f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34629f4ada15SMatthew G. Knepley   if (mesh->tr) {
34639f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
34649f4ada15SMatthew G. Knepley   } else {
34659f4ada15SMatthew G. Knepley     PetscInt off;
34669f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
34679f4ada15SMatthew G. Knepley       PetscInt dof;
34689f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
34699f4ada15SMatthew G. Knepley       if (dof) {
34704f572ea9SToby Isaac         if (cone) PetscAssertPointer(cone, 3);
34714f572ea9SToby Isaac         if (ornt) PetscAssertPointer(ornt, 4);
34729f4ada15SMatthew G. Knepley       }
34739f4ada15SMatthew G. Knepley     }
34749f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3475072f5ffdSStefano Zampini     if (cone) *cone = mesh->cones ? mesh->cones + off : NULL; // NULL + 0 is UB
3476072f5ffdSStefano Zampini     if (ornt) *ornt = mesh->coneOrientations ? mesh->coneOrientations + off : NULL;
34779f4ada15SMatthew G. Knepley   }
34783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34799f4ada15SMatthew G. Knepley }
34809f4ada15SMatthew G. Knepley 
34819f4ada15SMatthew G. Knepley /*@C
34829f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
34839f4ada15SMatthew G. Knepley 
348420f4b53cSBarry Smith   Not Collective
34859f4ada15SMatthew G. Knepley 
34869f4ada15SMatthew G. Knepley   Input Parameters:
34879f4ada15SMatthew G. Knepley + dm   - The DMPlex
348820f4b53cSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
34899f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
349020f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
34919f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
34929f4ada15SMatthew G. Knepley 
34939f4ada15SMatthew G. Knepley   Level: beginner
34949f4ada15SMatthew G. Knepley 
34959f4ada15SMatthew G. Knepley   Notes:
34969f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
34979f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
349820f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
34999f4ada15SMatthew G. Knepley   with the identity.
35009f4ada15SMatthew G. Knepley 
350160225df5SJacob Faibussowitsch   Fortran Notes:
350220f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
350320f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
35049f4ada15SMatthew G. Knepley 
35051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
35069f4ada15SMatthew G. Knepley @*/
35079f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
35089f4ada15SMatthew G. Knepley {
35099f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
35109f4ada15SMatthew G. Knepley 
35119f4ada15SMatthew G. Knepley   PetscFunctionBegin;
35129f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35139f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
35143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35159f4ada15SMatthew G. Knepley }
35169f4ada15SMatthew G. Knepley 
3517552f7358SJed Brown /*@
3518eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3519552f7358SJed Brown 
3520a1cb98faSBarry Smith   Not Collective
3521552f7358SJed Brown 
3522552f7358SJed Brown   Input Parameters:
352360225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3524a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3525552f7358SJed Brown 
3526552f7358SJed Brown   Output Parameter:
352720f4b53cSBarry Smith . size - The support size for point `p`
3528552f7358SJed Brown 
3529552f7358SJed Brown   Level: beginner
3530552f7358SJed Brown 
35311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3532552f7358SJed Brown @*/
3533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3534d71ae5a4SJacob Faibussowitsch {
3535552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3536552f7358SJed Brown 
3537552f7358SJed Brown   PetscFunctionBegin;
3538552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35394f572ea9SToby Isaac   PetscAssertPointer(size, 3);
35409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
35413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3542552f7358SJed Brown }
3543552f7358SJed Brown 
3544552f7358SJed Brown /*@
3545eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3546552f7358SJed Brown 
3547a1cb98faSBarry Smith   Not Collective
3548552f7358SJed Brown 
3549552f7358SJed Brown   Input Parameters:
355060225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3551a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
355220f4b53cSBarry Smith - size - The support size for point `p`
3553552f7358SJed Brown 
3554a1cb98faSBarry Smith   Level: beginner
3555552f7358SJed Brown 
3556552f7358SJed Brown   Note:
355720f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3558552f7358SJed Brown 
35591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3560552f7358SJed Brown @*/
3561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3562d71ae5a4SJacob Faibussowitsch {
3563552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3564552f7358SJed Brown 
3565552f7358SJed Brown   PetscFunctionBegin;
3566552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
35683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3569552f7358SJed Brown }
3570552f7358SJed Brown 
3571552f7358SJed Brown /*@C
3572eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3573552f7358SJed Brown 
3574a1cb98faSBarry Smith   Not Collective
3575552f7358SJed Brown 
3576552f7358SJed Brown   Input Parameters:
357760225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3578a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3579552f7358SJed Brown 
3580552f7358SJed Brown   Output Parameter:
358120f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3582552f7358SJed Brown 
3583552f7358SJed Brown   Level: beginner
3584552f7358SJed Brown 
358560225df5SJacob Faibussowitsch   Fortran Notes:
3586a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3587a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
35883813dfbdSMatthew G Knepley 
35891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3590552f7358SJed Brown @*/
3591d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3592d71ae5a4SJacob Faibussowitsch {
3593552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3594552f7358SJed Brown   PetscInt off;
3595552f7358SJed Brown 
3596552f7358SJed Brown   PetscFunctionBegin;
3597552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35984f572ea9SToby Isaac   PetscAssertPointer(support, 3);
35999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3600072f5ffdSStefano Zampini   *support = mesh->supports ? mesh->supports + off : NULL; //NULL + 0 is UB
36013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3602552f7358SJed Brown }
3603552f7358SJed Brown 
3604552f7358SJed Brown /*@
360592371b87SBarry 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
3606552f7358SJed Brown 
3607a1cb98faSBarry Smith   Not Collective
3608552f7358SJed Brown 
3609552f7358SJed Brown   Input Parameters:
361060225df5SJacob Faibussowitsch + dm      - The `DMPLEX`
3611a1cb98faSBarry Smith . p       - The point, which must lie in the chart set with `DMPlexSetChart()`
361220f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3613552f7358SJed Brown 
3614552f7358SJed Brown   Level: beginner
3615552f7358SJed Brown 
3616a1cb98faSBarry Smith   Note:
3617a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3618a1cb98faSBarry Smith 
36191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3620552f7358SJed Brown @*/
3621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3622d71ae5a4SJacob Faibussowitsch {
3623552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3624552f7358SJed Brown   PetscInt pStart, pEnd;
3625552f7358SJed Brown   PetscInt dof, off, c;
3626552f7358SJed Brown 
3627552f7358SJed Brown   PetscFunctionBegin;
3628552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
36314f572ea9SToby Isaac   if (dof) PetscAssertPointer(support, 3);
36329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
363363a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3634552f7358SJed Brown   for (c = 0; c < dof; ++c) {
363563a3b9bcSJacob Faibussowitsch     PetscCheck(!(support[c] < pStart) && !(support[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", support[c], pStart, pEnd);
3636552f7358SJed Brown     mesh->supports[off + c] = support[c];
3637552f7358SJed Brown   }
36383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3639552f7358SJed Brown }
3640552f7358SJed Brown 
36417cd05799SMatthew G. Knepley /*@
3642eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
36437cd05799SMatthew G. Knepley 
3644a1cb98faSBarry Smith   Not Collective
36457cd05799SMatthew G. Knepley 
36467cd05799SMatthew G. Knepley   Input Parameters:
364760225df5SJacob Faibussowitsch + dm           - The `DMPLEX`
3648a1cb98faSBarry Smith . p            - The point, which must lie in the chart set with `DMPlexSetChart()`
36497cd05799SMatthew G. Knepley . supportPos   - The local index in the cone where the point should be put
36507cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
36517cd05799SMatthew G. Knepley 
36527cd05799SMatthew G. Knepley   Level: beginner
36537cd05799SMatthew G. Knepley 
36541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
36557cd05799SMatthew G. Knepley @*/
3656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3657d71ae5a4SJacob Faibussowitsch {
3658552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3659552f7358SJed Brown   PetscInt pStart, pEnd;
3660552f7358SJed Brown   PetscInt dof, off;
3661552f7358SJed Brown 
3662552f7358SJed Brown   PetscFunctionBegin;
3663552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
36669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
366763a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
366863a3b9bcSJacob Faibussowitsch   PetscCheck(!(supportPoint < pStart) && !(supportPoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", supportPoint, pStart, pEnd);
366963a3b9bcSJacob Faibussowitsch   PetscCheck(supportPos < dof, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", supportPos, p, dof);
3670552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
36713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3672552f7358SJed Brown }
3673552f7358SJed Brown 
3674b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3675d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3676d71ae5a4SJacob Faibussowitsch {
3677b5a892a1SMatthew G. Knepley   switch (ct) {
3678b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3679b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3680b5a892a1SMatthew G. Knepley     break;
3681b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3682b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3683b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3684b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3685b5a892a1SMatthew G. Knepley     break;
3686b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3687b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3688b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3689b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3690b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3691b5a892a1SMatthew G. Knepley     break;
3692d71ae5a4SJacob Faibussowitsch   default:
3693d71ae5a4SJacob Faibussowitsch     return o;
3694b5a892a1SMatthew G. Knepley   }
3695b5a892a1SMatthew G. Knepley   return o;
3696b5a892a1SMatthew G. Knepley }
3697b5a892a1SMatthew G. Knepley 
3698b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3699d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3700d71ae5a4SJacob Faibussowitsch {
3701b5a892a1SMatthew G. Knepley   switch (ct) {
3702b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3703b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3704b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3705b5a892a1SMatthew G. Knepley     break;
3706b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3707b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3708b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3709b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3710b5a892a1SMatthew G. Knepley     break;
3711b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3712b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3713b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3714b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3715b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3716b5a892a1SMatthew G. Knepley     break;
3717d71ae5a4SJacob Faibussowitsch   default:
3718d71ae5a4SJacob Faibussowitsch     return o;
3719b5a892a1SMatthew G. Knepley   }
3720b5a892a1SMatthew G. Knepley   return o;
3721b5a892a1SMatthew G. Knepley }
3722b5a892a1SMatthew G. Knepley 
3723b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3725d71ae5a4SJacob Faibussowitsch {
3726b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3727b5a892a1SMatthew G. Knepley 
3728b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
37299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3730b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3731b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3732b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3733b5a892a1SMatthew G. Knepley 
37349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
37359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
37369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3737b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3738b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3739b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3740b5a892a1SMatthew G. Knepley 
37419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3742b5a892a1SMatthew G. Knepley       switch (ct) {
3743b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
37449566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37459566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3746b5a892a1SMatthew G. Knepley         break;
3747b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
37489566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37499566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37509566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3751b5a892a1SMatthew G. Knepley         break;
3752b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
37539566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37549566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37559566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
37569566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3757b5a892a1SMatthew G. Knepley         break;
3758d71ae5a4SJacob Faibussowitsch       default:
3759d71ae5a4SJacob Faibussowitsch         break;
3760b5a892a1SMatthew G. Knepley       }
3761b5a892a1SMatthew G. Knepley     }
3762b5a892a1SMatthew G. Knepley   }
37633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3764b5a892a1SMatthew G. Knepley }
3765b5a892a1SMatthew G. Knepley 
376609015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
376709015e70SStefano Zampini {
376809015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
376909015e70SStefano Zampini 
377009015e70SStefano Zampini   PetscFunctionBeginHot;
377109015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
377209015e70SStefano Zampini     if (useCone) {
377309015e70SStefano Zampini       PetscCall(DMPlexGetConeSize(dm, p, size));
377409015e70SStefano Zampini       PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt));
377509015e70SStefano Zampini     } else {
377609015e70SStefano Zampini       PetscCall(DMPlexGetSupportSize(dm, p, size));
377709015e70SStefano Zampini       PetscCall(DMPlexGetSupport(dm, p, arr));
377809015e70SStefano Zampini     }
377909015e70SStefano Zampini   } else {
378009015e70SStefano Zampini     if (useCone) {
378109015e70SStefano Zampini       const PetscSection s   = mesh->coneSection;
378209015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
378309015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
378409015e70SStefano Zampini 
378509015e70SStefano Zampini       *size = s->atlasDof[ps];
378609015e70SStefano Zampini       *arr  = mesh->cones + off;
378709015e70SStefano Zampini       *ornt = mesh->coneOrientations + off;
378809015e70SStefano Zampini     } else {
378909015e70SStefano Zampini       const PetscSection s   = mesh->supportSection;
379009015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
379109015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
379209015e70SStefano Zampini 
379309015e70SStefano Zampini       *size = s->atlasDof[ps];
379409015e70SStefano Zampini       *arr  = mesh->supports + off;
379509015e70SStefano Zampini     }
379609015e70SStefano Zampini   }
379709015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
379809015e70SStefano Zampini }
379909015e70SStefano Zampini 
380009015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
380109015e70SStefano Zampini {
380209015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
380309015e70SStefano Zampini 
380409015e70SStefano Zampini   PetscFunctionBeginHot;
380509015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
380609015e70SStefano Zampini     if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt));
380709015e70SStefano Zampini   }
380809015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
380909015e70SStefano Zampini }
381009015e70SStefano Zampini 
3811d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3812d71ae5a4SJacob Faibussowitsch {
3813b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3814b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3815b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3816b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3817b5a892a1SMatthew G. Knepley 
3818b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3819b5a892a1SMatthew G. Knepley   if (ornt) {
38209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3821476787b7SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN;
3822b5a892a1SMatthew G. Knepley   }
3823b5a892a1SMatthew G. Knepley   if (*points) {
3824b5a892a1SMatthew G. Knepley     closure = *points;
3825b5a892a1SMatthew G. Knepley   } else {
3826b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
38279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
38289566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3829b5a892a1SMatthew G. Knepley   }
383009015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3831b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3832b5a892a1SMatthew G. Knepley     closure[off++] = p;
3833b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3834b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3835b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3836b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3837b5a892a1SMatthew G. Knepley     }
3838b5a892a1SMatthew G. Knepley   } else {
38395f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3840b5a892a1SMatthew G. Knepley 
3841b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3842b5a892a1SMatthew G. Knepley     closure[off++] = p;
3843b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3844b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3845b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3846b5a892a1SMatthew G. Knepley 
38479566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3848b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3849b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3850b5a892a1SMatthew G. Knepley     }
3851b5a892a1SMatthew G. Knepley   }
385209015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3853b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3854b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3856b5a892a1SMatthew G. Knepley }
3857b5a892a1SMatthew G. Knepley 
3858d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3859d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3860d71ae5a4SJacob Faibussowitsch {
3861b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3862b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3863b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3864b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3865b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3866b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3867b5a892a1SMatthew G. Knepley 
3868b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
38699566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
387009015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
38719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3872b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3873b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3874b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
38759371c9d4SSatish Balay   if (*points) {
38769371c9d4SSatish Balay     pts = *points;
38779371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3878b5a892a1SMatthew G. Knepley   c        = 0;
3879b5a892a1SMatthew G. Knepley   pts[c++] = point;
3880b5a892a1SMatthew G. Knepley   pts[c++] = o;
38819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
38829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
38839371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
38849371c9d4SSatish Balay     pts[c++] = closure[cl];
38859371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
38869371c9d4SSatish Balay   }
38879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
38889371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
38899371c9d4SSatish Balay     pts[c++] = closure[cl];
38909371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
38919371c9d4SSatish Balay   }
38929566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3893b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
38949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3895b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3896b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3897b5a892a1SMatthew G. Knepley   }
389809015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
3899b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3900b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3901b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3902b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3903b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3904b5a892a1SMatthew G. Knepley 
39059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3906b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
390709015e70SStefano Zampini       PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3908b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3909b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3910b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3911b5a892a1SMatthew G. Knepley 
39129371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
39139371c9d4SSatish Balay           if (pts[i] == cp) break;
3914b5a892a1SMatthew G. Knepley         if (i == c) {
39159566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3916b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3917b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3918b5a892a1SMatthew G. Knepley         }
3919b5a892a1SMatthew G. Knepley       }
392009015e70SStefano Zampini       PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3921b5a892a1SMatthew G. Knepley     }
3922b5a892a1SMatthew G. Knepley   }
3923b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3924b5a892a1SMatthew G. Knepley   *points    = pts;
39253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3926b5a892a1SMatthew G. Knepley }
3927b5a892a1SMatthew G. Knepley 
3928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3929d71ae5a4SJacob Faibussowitsch {
3930b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3931b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3932b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3933b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3934b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3935b5a892a1SMatthew G. Knepley 
3936b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3938b5a892a1SMatthew G. Knepley   if (depth == 1) {
39399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
39403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3941b5a892a1SMatthew G. Knepley   }
39429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3943476787b7SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN;
3944*c306944fSJed Brown   if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
39459566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
39463ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3947b5a892a1SMatthew G. Knepley   }
39489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3949b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3950b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3951b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39529566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
39539371c9d4SSatish Balay   if (*points) {
39549371c9d4SSatish Balay     closure = *points;
39559371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3956b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3957b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3958b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3959b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3960b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3961b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3962b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3963b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3964b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3965b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
3966b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
396709015e70SStefano Zampini     const PetscInt      *tmp, *tmpO = NULL;
3968b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3969b5a892a1SMatthew G. Knepley 
3970b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3971b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2;
397263a3b9bcSJacob Faibussowitsch       PetscCheck(!o || !(o >= nO || o < -nO), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ") for %s %" PetscInt_FMT, o, -nO, nO, DMPolytopeTypes[qt], q);
3973b5a892a1SMatthew G. Knepley     }
397409015e70SStefano Zampini     PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
3975b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3976b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
3977b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
3978b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
39799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3980b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3981b5a892a1SMatthew G. Knepley       PetscInt       c;
3982b5a892a1SMatthew G. Knepley 
3983b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3984b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3985b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3986b5a892a1SMatthew G. Knepley       }
3987b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3988b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3989b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3990b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3991b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3992b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3993b5a892a1SMatthew G. Knepley       }
3994b5a892a1SMatthew G. Knepley     }
399509015e70SStefano Zampini     PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
3996b5a892a1SMatthew G. Knepley   }
39979566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
3998b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
3999b5a892a1SMatthew G. Knepley   if (points) *points = closure;
40003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4001b5a892a1SMatthew G. Knepley }
4002b5a892a1SMatthew G. Knepley 
4003552f7358SJed Brown /*@C
4004eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
4005552f7358SJed Brown 
4006a1cb98faSBarry Smith   Not Collective
4007552f7358SJed Brown 
4008552f7358SJed Brown   Input Parameters:
4009a1cb98faSBarry Smith + dm      - The `DMPLEX`
4010b5a892a1SMatthew G. Knepley . p       - The mesh point
4011a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
4012552f7358SJed Brown 
40136b867d5aSJose E. Roman   Input/Output Parameter:
40146b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
401520f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
40166b867d5aSJose E. Roman 
40176b867d5aSJose E. Roman   Output Parameter:
401820f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4019552f7358SJed Brown 
4020a1cb98faSBarry Smith   Level: beginner
4021a1cb98faSBarry Smith 
4022552f7358SJed Brown   Note:
402320f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
4024552f7358SJed Brown 
402560225df5SJacob Faibussowitsch   Fortran Notes:
402620f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
40273813dfbdSMatthew G Knepley 
40281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4029552f7358SJed Brown @*/
4030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4031d71ae5a4SJacob Faibussowitsch {
4032b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4033552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40344f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(numPoints, 4);
40354f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 5);
40369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
40373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40389bf0dad6SMatthew G. Knepley }
40399bf0dad6SMatthew G. Knepley 
4040552f7358SJed Brown /*@C
4041eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
4042552f7358SJed Brown 
4043a1cb98faSBarry Smith   Not Collective
4044552f7358SJed Brown 
4045552f7358SJed Brown   Input Parameters:
4046a1cb98faSBarry Smith + dm        - The `DMPLEX`
4047b5a892a1SMatthew G. Knepley . p         - The mesh point
4048a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
404920f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4050b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
4051552f7358SJed Brown 
4052a1cb98faSBarry Smith   Level: beginner
4053a1cb98faSBarry Smith 
4054552f7358SJed Brown   Note:
405520f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
4056552f7358SJed Brown 
40571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4058552f7358SJed Brown @*/
4059d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4060d71ae5a4SJacob Faibussowitsch {
4061b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4062552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40634ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
40649566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
40653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4066552f7358SJed Brown }
4067552f7358SJed Brown 
4068552f7358SJed Brown /*@
4069eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
4070552f7358SJed Brown 
4071a1cb98faSBarry Smith   Not Collective
4072552f7358SJed Brown 
4073552f7358SJed Brown   Input Parameter:
407460225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4075552f7358SJed Brown 
4076552f7358SJed Brown   Output Parameters:
4077552f7358SJed Brown + maxConeSize    - The maximum number of in-edges
4078552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
4079552f7358SJed Brown 
4080552f7358SJed Brown   Level: beginner
4081552f7358SJed Brown 
40821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
4083552f7358SJed Brown @*/
4084d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
4085d71ae5a4SJacob Faibussowitsch {
4086552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
4087552f7358SJed Brown 
4088552f7358SJed Brown   PetscFunctionBegin;
4089552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40901baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
40911baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
40923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4093552f7358SJed Brown }
4094552f7358SJed Brown 
4095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
4096d71ae5a4SJacob Faibussowitsch {
4097552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
40986302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
4099552f7358SJed Brown 
4100552f7358SJed Brown   PetscFunctionBegin;
4101552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
41039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
41049566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
41059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
41066302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41076302a7fbSVaclav Hapla   if (maxSupportSize) {
41089566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
41099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
41109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
4111552f7358SJed Brown   }
41123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4113552f7358SJed Brown }
4114552f7358SJed Brown 
4115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
4116d71ae5a4SJacob Faibussowitsch {
4117552f7358SJed Brown   PetscFunctionBegin;
41189566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
41199566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
4120ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
4121736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
412295602cf2SAlexis Marboeuf     PetscSF sfNatural;
4123f94b4a02SBlaise Bourdin 
41243dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
41259566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
412695602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
4127c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
4128f94b4a02SBlaise Bourdin   }
41293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4130552f7358SJed Brown }
4131552f7358SJed Brown 
4132d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
4133d71ae5a4SJacob Faibussowitsch {
41343dcd263cSBlaise Bourdin   PetscInt i = 0;
41352adcc780SMatthew G. Knepley 
41362adcc780SMatthew G. Knepley   PetscFunctionBegin;
41379566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
41389566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
4139c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
41403dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
41413dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
414295602cf2SAlexis Marboeuf       PetscSF sfNatural;
41433dcd263cSBlaise Bourdin 
41443dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
41459566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
4146c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
414795602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
4148c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
41493dcd263cSBlaise Bourdin       break;
41503dcd263cSBlaise Bourdin     }
41513dcd263cSBlaise Bourdin   }
41523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41532adcc780SMatthew G. Knepley }
41542adcc780SMatthew G. Knepley 
4155552f7358SJed Brown /*@
4156eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
4157552f7358SJed Brown 
4158a1cb98faSBarry Smith   Not Collective
4159552f7358SJed Brown 
4160552f7358SJed Brown   Input Parameter:
416160225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4162552f7358SJed Brown 
4163552f7358SJed Brown   Level: beginner
4164552f7358SJed Brown 
4165a1cb98faSBarry Smith   Note:
4166a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
4167a1cb98faSBarry Smith 
41681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
4169552f7358SJed Brown @*/
4170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
4171d71ae5a4SJacob Faibussowitsch {
4172552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4173552f7358SJed Brown   PetscInt *offsets;
4174552f7358SJed Brown   PetscInt  supportSize;
4175552f7358SJed Brown   PetscInt  pStart, pEnd, p;
4176552f7358SJed Brown 
4177552f7358SJed Brown   PetscFunctionBegin;
4178552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
417928b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
41809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
4181552f7358SJed Brown   /* Calculate support sizes */
41829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4183552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4184552f7358SJed Brown     PetscInt dof, off, c;
4185552f7358SJed Brown 
41869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
41879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
418848a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4189552f7358SJed Brown   }
41909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4191552f7358SJed Brown   /* Calculate supports */
41929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
41939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
41949566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4195552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4196552f7358SJed Brown     PetscInt dof, off, c;
4197552f7358SJed Brown 
41989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
41999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4200552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4201552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4202552f7358SJed Brown       PetscInt       offS;
4203552f7358SJed Brown 
42049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
42050d644c17SKarl Rupp 
4206552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4207552f7358SJed Brown       ++offsets[q];
4208552f7358SJed Brown     }
4209552f7358SJed Brown   }
42109566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
42119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
42123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4213552f7358SJed Brown }
4214552f7358SJed Brown 
4215d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4216d71ae5a4SJacob Faibussowitsch {
4217277ea44aSLisandro Dalcin   IS stratumIS;
4218277ea44aSLisandro Dalcin 
4219277ea44aSLisandro Dalcin   PetscFunctionBegin;
42203ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
422176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4222277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4223277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
42249566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4225277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
42269566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
42279371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
42289371c9d4SSatish Balay         overlap = PETSC_TRUE;
42299371c9d4SSatish Balay         break;
42309371c9d4SSatish Balay       }
4231277ea44aSLisandro Dalcin     }
423263a3b9bcSJacob Faibussowitsch     PetscCheck(!overlap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ") overlaps with depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ")", depth, pStart, pEnd, level, qStart, qEnd);
4233277ea44aSLisandro Dalcin   }
42349566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
42359566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
42369566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
42373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4238277ea44aSLisandro Dalcin }
4239277ea44aSLisandro Dalcin 
4240552f7358SJed Brown /*@
4241a4e35b19SJacob Faibussowitsch   DMPlexStratify - Computes the strata for all points in the `DMPLEX`
4242552f7358SJed Brown 
424320f4b53cSBarry Smith   Collective
4244552f7358SJed Brown 
4245552f7358SJed Brown   Input Parameter:
424660225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4247552f7358SJed Brown 
4248a1cb98faSBarry Smith   Level: beginner
4249552f7358SJed Brown 
4250552f7358SJed Brown   Notes:
4251a4e35b19SJacob Faibussowitsch   The strata group all points of the same grade, and this function calculates the strata. This
4252a4e35b19SJacob Faibussowitsch   grade can be seen as the height (or depth) of the point in the DAG.
4253a4e35b19SJacob Faibussowitsch 
4254a4e35b19SJacob Faibussowitsch   The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
4255a4e35b19SJacob Faibussowitsch   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram).
4256a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4257b1bb481bSMatthew 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
4258a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4259a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4260a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4261552f7358SJed Brown 
4262b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4263b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4264b1bb481bSMatthew 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
4265b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4266a1cb98faSBarry Smith .vb
4267a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4268a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4269a1cb98faSBarry Smith .ve
4270a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4271a1cb98faSBarry Smith .vb
4272a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4273a1cb98faSBarry Smith    depth 1 = {e0, c0}
4274a1cb98faSBarry Smith .ve
4275b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4276b1bb481bSMatthew Knepley 
4277a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4278552f7358SJed Brown 
42791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4280552f7358SJed Brown @*/
4281d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4282d71ae5a4SJacob Faibussowitsch {
4283df0420ecSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4284aa50250dSMatthew G. Knepley   DMLabel  label;
4285552f7358SJed Brown   PetscInt pStart, pEnd, p;
4286552f7358SJed Brown   PetscInt numRoots = 0, numLeaves = 0;
4287552f7358SJed Brown 
4288552f7358SJed Brown   PetscFunctionBegin;
4289552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4291277ea44aSLisandro Dalcin 
4292277ea44aSLisandro Dalcin   /* Create depth label */
42939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
42949566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
42959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4296277ea44aSLisandro Dalcin 
4297277ea44aSLisandro Dalcin   {
4298552f7358SJed Brown     /* Initialize roots and count leaves */
4299277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4300277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4301552f7358SJed Brown     PetscInt coneSize, supportSize;
4302552f7358SJed Brown 
4303277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
43049566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
43059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4306552f7358SJed Brown       if (!coneSize && supportSize) {
4307277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4308277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4309552f7358SJed Brown         ++numRoots;
4310552f7358SJed Brown       } else if (!supportSize && coneSize) {
4311552f7358SJed Brown         ++numLeaves;
4312552f7358SJed Brown       } else if (!supportSize && !coneSize) {
4313552f7358SJed Brown         /* Isolated points */
4314277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4315277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4316552f7358SJed Brown       }
4317552f7358SJed Brown     }
43189566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4319277ea44aSLisandro Dalcin   }
4320277ea44aSLisandro Dalcin 
4321552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
4322277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4323277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4324552f7358SJed Brown     PetscInt coneSize, supportSize;
4325552f7358SJed Brown 
4326277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
43279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
43289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4329552f7358SJed Brown       if (!supportSize && coneSize) {
4330277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4331277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4332552f7358SJed Brown       }
4333552f7358SJed Brown     }
43349566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4335552f7358SJed Brown   } else {
4336277ea44aSLisandro Dalcin     PetscInt level = 0;
4337277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
4338552f7358SJed Brown 
43399566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4340277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4341277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4342277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
434374ef644bSMatthew G. Knepley 
4344277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
434574ef644bSMatthew G. Knepley         const PetscInt *support;
434674ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
434774ef644bSMatthew G. Knepley 
43489566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
43499566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
435074ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4351277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4352277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4353552f7358SJed Brown         }
4354552f7358SJed Brown       }
43559566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
43569566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
43579566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
435874ef644bSMatthew G. Knepley     }
435974ef644bSMatthew G. Knepley   }
4360bf4602e4SToby Isaac   { /* just in case there is an empty process */
4361bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4362bf4602e4SToby Isaac 
43639566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4364712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
436548a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4366bf4602e4SToby Isaac   }
43679566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
43689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
43693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4370552f7358SJed Brown }
4371552f7358SJed Brown 
4372d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4373d71ae5a4SJacob Faibussowitsch {
4374412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4375412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4376ba2698f1SMatthew G. Knepley 
4377412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
43789566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
43799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
43809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4381ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4382ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4383ba2698f1SMatthew G. Knepley     switch (pdepth) {
4384d71ae5a4SJacob Faibussowitsch     case 0:
4385d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4386d71ae5a4SJacob Faibussowitsch       break;
4387ba2698f1SMatthew G. Knepley     case 1:
4388ba2698f1SMatthew G. Knepley       switch (coneSize) {
4389d71ae5a4SJacob Faibussowitsch       case 2:
4390d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4391d71ae5a4SJacob Faibussowitsch         break;
4392d71ae5a4SJacob Faibussowitsch       case 3:
4393d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4394d71ae5a4SJacob Faibussowitsch         break;
4395ba2698f1SMatthew G. Knepley       case 4:
4396ba2698f1SMatthew G. Knepley         switch (dim) {
4397d71ae5a4SJacob Faibussowitsch         case 2:
4398d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4399d71ae5a4SJacob Faibussowitsch           break;
4400d71ae5a4SJacob Faibussowitsch         case 3:
4401d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4402d71ae5a4SJacob Faibussowitsch           break;
4403d71ae5a4SJacob Faibussowitsch         default:
4404d71ae5a4SJacob Faibussowitsch           break;
4405ba2698f1SMatthew G. Knepley         }
4406ba2698f1SMatthew G. Knepley         break;
4407d71ae5a4SJacob Faibussowitsch       case 5:
4408d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4409d71ae5a4SJacob Faibussowitsch         break;
4410d71ae5a4SJacob Faibussowitsch       case 6:
4411d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4412d71ae5a4SJacob Faibussowitsch         break;
4413d71ae5a4SJacob Faibussowitsch       case 8:
4414d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4415d71ae5a4SJacob Faibussowitsch         break;
4416d71ae5a4SJacob Faibussowitsch       default:
4417d71ae5a4SJacob Faibussowitsch         break;
4418ba2698f1SMatthew G. Knepley       }
4419ba2698f1SMatthew G. Knepley     }
4420ba2698f1SMatthew G. Knepley   } else {
4421ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4422ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4423ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4424ba2698f1SMatthew G. Knepley       switch (dim) {
4425ba2698f1SMatthew G. Knepley       case 1:
4426ba2698f1SMatthew G. Knepley         switch (coneSize) {
4427d71ae5a4SJacob Faibussowitsch         case 2:
4428d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4429d71ae5a4SJacob Faibussowitsch           break;
4430d71ae5a4SJacob Faibussowitsch         default:
4431d71ae5a4SJacob Faibussowitsch           break;
4432ba2698f1SMatthew G. Knepley         }
4433ba2698f1SMatthew G. Knepley         break;
4434ba2698f1SMatthew G. Knepley       case 2:
4435ba2698f1SMatthew G. Knepley         switch (coneSize) {
4436d71ae5a4SJacob Faibussowitsch         case 3:
4437d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4438d71ae5a4SJacob Faibussowitsch           break;
4439d71ae5a4SJacob Faibussowitsch         case 4:
4440d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4441d71ae5a4SJacob Faibussowitsch           break;
4442d71ae5a4SJacob Faibussowitsch         default:
4443d71ae5a4SJacob Faibussowitsch           break;
4444ba2698f1SMatthew G. Knepley         }
4445ba2698f1SMatthew G. Knepley         break;
4446ba2698f1SMatthew G. Knepley       case 3:
4447ba2698f1SMatthew G. Knepley         switch (coneSize) {
4448d71ae5a4SJacob Faibussowitsch         case 4:
4449d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4450d71ae5a4SJacob Faibussowitsch           break;
44519371c9d4SSatish Balay         case 5: {
4452da9060c4SMatthew G. Knepley           const PetscInt *cone;
4453da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4454da9060c4SMatthew G. Knepley 
44559566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
44569566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4457da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4458d71ae5a4SJacob Faibussowitsch           case 3:
4459d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4460d71ae5a4SJacob Faibussowitsch             break;
4461d71ae5a4SJacob Faibussowitsch           case 4:
4462d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4463d71ae5a4SJacob Faibussowitsch             break;
4464da9060c4SMatthew G. Knepley           }
44659371c9d4SSatish Balay         } break;
4466d71ae5a4SJacob Faibussowitsch         case 6:
4467d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4468d71ae5a4SJacob Faibussowitsch           break;
4469d71ae5a4SJacob Faibussowitsch         default:
4470d71ae5a4SJacob Faibussowitsch           break;
4471ba2698f1SMatthew G. Knepley         }
4472ba2698f1SMatthew G. Knepley         break;
4473d71ae5a4SJacob Faibussowitsch       default:
4474d71ae5a4SJacob Faibussowitsch         break;
4475ba2698f1SMatthew G. Knepley       }
4476ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4477ba2698f1SMatthew G. Knepley       switch (coneSize) {
4478d71ae5a4SJacob Faibussowitsch       case 2:
4479d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4480d71ae5a4SJacob Faibussowitsch         break;
4481d71ae5a4SJacob Faibussowitsch       case 3:
4482d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4483d71ae5a4SJacob Faibussowitsch         break;
4484d71ae5a4SJacob Faibussowitsch       case 4:
4485d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4486d71ae5a4SJacob Faibussowitsch         break;
4487d71ae5a4SJacob Faibussowitsch       default:
4488d71ae5a4SJacob Faibussowitsch         break;
4489ba2698f1SMatthew G. Knepley       }
4490ba2698f1SMatthew G. Knepley     }
4491ba2698f1SMatthew G. Knepley   }
4492412e9a14SMatthew G. Knepley   *pt = ct;
44933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4494ba2698f1SMatthew G. Knepley }
4495412e9a14SMatthew G. Knepley 
4496412e9a14SMatthew G. Knepley /*@
4497412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4498412e9a14SMatthew G. Knepley 
449920f4b53cSBarry Smith   Collective
4500412e9a14SMatthew G. Knepley 
4501412e9a14SMatthew G. Knepley   Input Parameter:
450260225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4503412e9a14SMatthew G. Knepley 
4504412e9a14SMatthew G. Knepley   Level: developer
4505412e9a14SMatthew G. Knepley 
4506a1cb98faSBarry Smith   Note:
4507a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4508a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4509a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4510412e9a14SMatthew G. Knepley 
4511a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4512a1cb98faSBarry Smith 
45131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4514412e9a14SMatthew G. Knepley @*/
4515d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4516d71ae5a4SJacob Faibussowitsch {
4517412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4518412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4519412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4520412e9a14SMatthew G. Knepley 
4521412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4522412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4523412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
45249566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
45259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
45269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
452721027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
452821027e53SStefano Zampini   PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
4529412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4530327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4531412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4532412e9a14SMatthew G. Knepley 
45339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
45349566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
4535476787b7SMatthew G. Knepley     PetscCheck(ct != DM_POLYTOPE_UNKNOWN && ct != DM_POLYTOPE_UNKNOWN_CELL && ct != DM_POLYTOPE_UNKNOWN_FACE, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
45369566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
453721027e53SStefano Zampini     mesh->cellTypes[p - pStart].value_as_uint8 = ct;
4538412e9a14SMatthew G. Knepley   }
45399566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
45409566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
45413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4542ba2698f1SMatthew G. Knepley }
4543ba2698f1SMatthew G. Knepley 
4544552f7358SJed Brown /*@C
4545552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4546552f7358SJed Brown 
4547552f7358SJed Brown   Not Collective
4548552f7358SJed Brown 
4549552f7358SJed Brown   Input Parameters:
4550a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4551552f7358SJed Brown . numPoints - The number of input points for the join
4552552f7358SJed Brown - points    - The input points
4553552f7358SJed Brown 
4554552f7358SJed Brown   Output Parameters:
4555552f7358SJed Brown + numCoveredPoints - The number of points in the join
4556552f7358SJed Brown - coveredPoints    - The points in the join
4557552f7358SJed Brown 
4558552f7358SJed Brown   Level: intermediate
4559552f7358SJed Brown 
4560a1cb98faSBarry Smith   Note:
4561a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4562552f7358SJed Brown 
456360225df5SJacob Faibussowitsch   Fortran Notes:
456420f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
45653813dfbdSMatthew G Knepley 
45661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4567552f7358SJed Brown @*/
4568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4569d71ae5a4SJacob Faibussowitsch {
4570552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4571552f7358SJed Brown   PetscInt *join[2];
4572552f7358SJed Brown   PetscInt  joinSize, i = 0;
4573552f7358SJed Brown   PetscInt  dof, off, p, c, m;
45746302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4575552f7358SJed Brown 
4576552f7358SJed Brown   PetscFunctionBegin;
4577552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45784f572ea9SToby Isaac   PetscAssertPointer(points, 3);
45794f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
45804f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
45816302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
45826302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
45836302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4584552f7358SJed Brown   /* Copy in support of first point */
45859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
45869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4587ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4588552f7358SJed Brown   /* Check each successive support */
4589552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4590552f7358SJed Brown     PetscInt newJoinSize = 0;
4591552f7358SJed Brown 
45929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
45939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4594552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4595552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4596552f7358SJed Brown 
4597552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4598552f7358SJed Brown         if (point == join[i][m]) {
4599552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4600552f7358SJed Brown           break;
4601552f7358SJed Brown         }
4602552f7358SJed Brown       }
4603552f7358SJed Brown     }
4604552f7358SJed Brown     joinSize = newJoinSize;
4605552f7358SJed Brown     i        = 1 - i;
4606552f7358SJed Brown   }
4607552f7358SJed Brown   *numCoveredPoints = joinSize;
4608552f7358SJed Brown   *coveredPoints    = join[i];
46096302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
46103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4611552f7358SJed Brown }
4612552f7358SJed Brown 
4613552f7358SJed Brown /*@C
4614552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4615552f7358SJed Brown 
4616552f7358SJed Brown   Not Collective
4617552f7358SJed Brown 
4618552f7358SJed Brown   Input Parameters:
4619a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4620552f7358SJed Brown . numPoints - The number of input points for the join
4621552f7358SJed Brown - points    - The input points
4622552f7358SJed Brown 
4623552f7358SJed Brown   Output Parameters:
4624552f7358SJed Brown + numCoveredPoints - The number of points in the join
4625552f7358SJed Brown - coveredPoints    - The points in the join
4626552f7358SJed Brown 
4627552f7358SJed Brown   Level: intermediate
4628552f7358SJed Brown 
462960225df5SJacob Faibussowitsch   Fortran Notes:
463020f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4631a1cb98faSBarry Smith 
46321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4633552f7358SJed Brown @*/
4634d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4635d71ae5a4SJacob Faibussowitsch {
4636552f7358SJed Brown   PetscFunctionBegin;
4637552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46384f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
46394f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
46404f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
46419566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4642d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
46433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4644552f7358SJed Brown }
4645552f7358SJed Brown 
4646552f7358SJed Brown /*@C
4647552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4648552f7358SJed Brown 
4649552f7358SJed Brown   Not Collective
4650552f7358SJed Brown 
4651552f7358SJed Brown   Input Parameters:
4652a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4653552f7358SJed Brown . numPoints - The number of input points for the join
4654552f7358SJed Brown - points    - The input points
4655552f7358SJed Brown 
4656552f7358SJed Brown   Output Parameters:
4657552f7358SJed Brown + numCoveredPoints - The number of points in the join
4658552f7358SJed Brown - coveredPoints    - The points in the join
4659552f7358SJed Brown 
4660552f7358SJed Brown   Level: intermediate
4661552f7358SJed Brown 
466260225df5SJacob Faibussowitsch   Fortran Notes:
466320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4664a1cb98faSBarry Smith 
46651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4666552f7358SJed Brown @*/
4667d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4668d71ae5a4SJacob Faibussowitsch {
4669552f7358SJed Brown   PetscInt *offsets, **closures;
4670552f7358SJed Brown   PetscInt *join[2];
4671552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
467224c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4673552f7358SJed Brown 
4674552f7358SJed Brown   PetscFunctionBegin;
4675552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46764f572ea9SToby Isaac   PetscAssertPointer(points, 3);
46774f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
46784f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4679552f7358SJed Brown 
46809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
46819566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
46829566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
46836302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
468424c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
46859566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
46869566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4687552f7358SJed Brown 
4688552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4689552f7358SJed Brown     PetscInt closureSize;
4690552f7358SJed Brown 
46919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
46920d644c17SKarl Rupp 
4693552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4694552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4695552f7358SJed Brown       PetscInt pStart, pEnd, i;
4696552f7358SJed Brown 
46979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4698552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4699552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4700552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4701552f7358SJed Brown           break;
4702552f7358SJed Brown         }
4703552f7358SJed Brown       }
4704552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4705552f7358SJed Brown     }
470663a3b9bcSJacob Faibussowitsch     PetscCheck(offsets[p * (depth + 2) + depth + 1] == closureSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p * (depth + 2) + depth + 1], closureSize);
4707552f7358SJed Brown   }
4708552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4709552f7358SJed Brown     PetscInt dof;
4710552f7358SJed Brown 
4711552f7358SJed Brown     /* Copy in support of first point */
4712552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4713ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4714552f7358SJed Brown     /* Check each successive cone */
4715552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4716552f7358SJed Brown       PetscInt newJoinSize = 0;
4717552f7358SJed Brown 
4718552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4719552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4720552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4721552f7358SJed Brown 
4722552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4723552f7358SJed Brown           if (point == join[i][m]) {
4724552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4725552f7358SJed Brown             break;
4726552f7358SJed Brown           }
4727552f7358SJed Brown         }
4728552f7358SJed Brown       }
4729552f7358SJed Brown       joinSize = newJoinSize;
4730552f7358SJed Brown       i        = 1 - i;
4731552f7358SJed Brown     }
4732552f7358SJed Brown     if (joinSize) break;
4733552f7358SJed Brown   }
4734552f7358SJed Brown   *numCoveredPoints = joinSize;
4735552f7358SJed Brown   *coveredPoints    = join[i];
473648a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
47379566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
47389566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
47396302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
47403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4741552f7358SJed Brown }
4742552f7358SJed Brown 
4743552f7358SJed Brown /*@C
4744552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4745552f7358SJed Brown 
4746552f7358SJed Brown   Not Collective
4747552f7358SJed Brown 
4748552f7358SJed Brown   Input Parameters:
4749a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4750552f7358SJed Brown . numPoints - The number of input points for the meet
4751552f7358SJed Brown - points    - The input points
4752552f7358SJed Brown 
4753552f7358SJed Brown   Output Parameters:
475460225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet
475560225df5SJacob Faibussowitsch - coveringPoints    - The points in the meet
4756552f7358SJed Brown 
4757552f7358SJed Brown   Level: intermediate
4758552f7358SJed Brown 
4759a1cb98faSBarry Smith   Note:
4760a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4761552f7358SJed Brown 
47623813dfbdSMatthew G Knepley   Fortran Notes:
476320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
47643813dfbdSMatthew G Knepley 
47651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4766552f7358SJed Brown @*/
4767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4768d71ae5a4SJacob Faibussowitsch {
4769552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4770552f7358SJed Brown   PetscInt *meet[2];
4771552f7358SJed Brown   PetscInt  meetSize, i = 0;
4772552f7358SJed Brown   PetscInt  dof, off, p, c, m;
47736302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4774552f7358SJed Brown 
4775552f7358SJed Brown   PetscFunctionBegin;
4776552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47774f572ea9SToby Isaac   PetscAssertPointer(points, 3);
47784f572ea9SToby Isaac   PetscAssertPointer(numCoveringPoints, 4);
47794f572ea9SToby Isaac   PetscAssertPointer(coveringPoints, 5);
47806302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
47816302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
47826302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4783552f7358SJed Brown   /* Copy in cone of first point */
47849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
47859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4786ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4787552f7358SJed Brown   /* Check each successive cone */
4788552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4789552f7358SJed Brown     PetscInt newMeetSize = 0;
4790552f7358SJed Brown 
47919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
47929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4793552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4794552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4795552f7358SJed Brown 
4796552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4797552f7358SJed Brown         if (point == meet[i][m]) {
4798552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4799552f7358SJed Brown           break;
4800552f7358SJed Brown         }
4801552f7358SJed Brown       }
4802552f7358SJed Brown     }
4803552f7358SJed Brown     meetSize = newMeetSize;
4804552f7358SJed Brown     i        = 1 - i;
4805552f7358SJed Brown   }
4806552f7358SJed Brown   *numCoveringPoints = meetSize;
4807552f7358SJed Brown   *coveringPoints    = meet[i];
48086302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
48093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4810552f7358SJed Brown }
4811552f7358SJed Brown 
4812552f7358SJed Brown /*@C
4813552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4814552f7358SJed Brown 
4815552f7358SJed Brown   Not Collective
4816552f7358SJed Brown 
4817552f7358SJed Brown   Input Parameters:
4818a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4819552f7358SJed Brown . numPoints - The number of input points for the meet
4820552f7358SJed Brown - points    - The input points
4821552f7358SJed Brown 
4822552f7358SJed Brown   Output Parameters:
4823552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4824552f7358SJed Brown - coveredPoints    - The points in the meet
4825552f7358SJed Brown 
4826552f7358SJed Brown   Level: intermediate
4827552f7358SJed Brown 
482860225df5SJacob Faibussowitsch   Fortran Notes:
482920f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
48303813dfbdSMatthew G Knepley 
48311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4832552f7358SJed Brown @*/
4833d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4834d71ae5a4SJacob Faibussowitsch {
4835552f7358SJed Brown   PetscFunctionBegin;
4836552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48374f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
48384f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
48394f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
48409566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4841d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
48423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4843552f7358SJed Brown }
4844552f7358SJed Brown 
4845552f7358SJed Brown /*@C
4846552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4847552f7358SJed Brown 
4848552f7358SJed Brown   Not Collective
4849552f7358SJed Brown 
4850552f7358SJed Brown   Input Parameters:
4851a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4852552f7358SJed Brown . numPoints - The number of input points for the meet
4853552f7358SJed Brown - points    - The input points
4854552f7358SJed Brown 
4855552f7358SJed Brown   Output Parameters:
4856552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4857552f7358SJed Brown - coveredPoints    - The points in the meet
4858552f7358SJed Brown 
4859552f7358SJed Brown   Level: intermediate
4860552f7358SJed Brown 
486160225df5SJacob Faibussowitsch   Fortran Notes:
486220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
48633813dfbdSMatthew G Knepley 
48641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4865552f7358SJed Brown @*/
4866d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4867d71ae5a4SJacob Faibussowitsch {
4868552f7358SJed Brown   PetscInt *offsets, **closures;
4869552f7358SJed Brown   PetscInt *meet[2];
4870552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
487124c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4872552f7358SJed Brown 
4873552f7358SJed Brown   PetscFunctionBegin;
4874552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48754f572ea9SToby Isaac   PetscAssertPointer(points, 3);
48764f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
48774f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4878552f7358SJed Brown 
48799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
48809566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
48819566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
48826302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
488324c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
48849566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
48859566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4886552f7358SJed Brown 
4887552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4888552f7358SJed Brown     PetscInt closureSize;
4889552f7358SJed Brown 
48909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
48910d644c17SKarl Rupp 
4892552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4893552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4894552f7358SJed Brown       PetscInt pStart, pEnd, i;
4895552f7358SJed Brown 
48969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4897552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4898552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4899552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4900552f7358SJed Brown           break;
4901552f7358SJed Brown         }
4902552f7358SJed Brown       }
4903552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4904552f7358SJed Brown     }
490563a3b9bcSJacob Faibussowitsch     PetscCheck(offsets[p * (height + 2) + height + 1] == closureSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p * (height + 2) + height + 1], closureSize);
4906552f7358SJed Brown   }
4907552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4908552f7358SJed Brown     PetscInt dof;
4909552f7358SJed Brown 
4910552f7358SJed Brown     /* Copy in cone of first point */
4911552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
4912ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
4913552f7358SJed Brown     /* Check each successive cone */
4914552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4915552f7358SJed Brown       PetscInt newMeetSize = 0;
4916552f7358SJed Brown 
4917552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
4918552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4919552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
4920552f7358SJed Brown 
4921552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4922552f7358SJed Brown           if (point == meet[i][m]) {
4923552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
4924552f7358SJed Brown             break;
4925552f7358SJed Brown           }
4926552f7358SJed Brown         }
4927552f7358SJed Brown       }
4928552f7358SJed Brown       meetSize = newMeetSize;
4929552f7358SJed Brown       i        = 1 - i;
4930552f7358SJed Brown     }
4931552f7358SJed Brown     if (meetSize) break;
4932552f7358SJed Brown   }
4933552f7358SJed Brown   *numCoveredPoints = meetSize;
4934552f7358SJed Brown   *coveredPoints    = meet[i];
493548a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
49369566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
49379566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
49386302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
49393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4940552f7358SJed Brown }
4941552f7358SJed Brown 
49424e3744c5SMatthew G. Knepley /*@C
4943a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
49444e3744c5SMatthew G. Knepley 
49454e3744c5SMatthew G. Knepley   Not Collective
49464e3744c5SMatthew G. Knepley 
49474e3744c5SMatthew G. Knepley   Input Parameters:
4948a1cb98faSBarry Smith + dmA - A `DMPLEX` object
4949a1cb98faSBarry Smith - dmB - A `DMPLEX` object
49504e3744c5SMatthew G. Knepley 
49512fe279fdSBarry Smith   Output Parameter:
4952a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
49534e3744c5SMatthew G. Knepley 
49544e3744c5SMatthew G. Knepley   Level: intermediate
49554e3744c5SMatthew G. Knepley 
4956a1cb98faSBarry Smith   Note:
49573c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
49584e3744c5SMatthew G. Knepley 
49591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
49604e3744c5SMatthew G. Knepley @*/
4961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
4962d71ae5a4SJacob Faibussowitsch {
49634e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
49644e3744c5SMatthew G. Knepley 
49654e3744c5SMatthew G. Knepley   PetscFunctionBegin;
49664e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
49674e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
49684f572ea9SToby Isaac   PetscAssertPointer(equal, 3);
49694e3744c5SMatthew G. Knepley 
49704e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
49719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
49729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
49733ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
49749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
49759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
49763ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
49774e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
49784e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
49794e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
49804e3744c5SMatthew G. Knepley 
49819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
49829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
49839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
49849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
49859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
49869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
49873ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
49884e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
49893ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
49903ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
49914e3744c5SMatthew G. Knepley     }
49929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
49939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
49949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
49959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
49963ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
49974e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
49983ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
49994e3744c5SMatthew G. Knepley     }
50004e3744c5SMatthew G. Knepley   }
50014e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
50023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50034e3744c5SMatthew G. Knepley }
50044e3744c5SMatthew G. Knepley 
50057cd05799SMatthew G. Knepley /*@C
50067cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
50077cd05799SMatthew G. Knepley 
50087cd05799SMatthew G. Knepley   Not Collective
50097cd05799SMatthew G. Knepley 
50107cd05799SMatthew G. Knepley   Input Parameters:
5011a1cb98faSBarry Smith + dm         - The `DMPLEX`
50127cd05799SMatthew G. Knepley . cellDim    - The cell dimension
50137cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
50147cd05799SMatthew G. Knepley 
50152fe279fdSBarry Smith   Output Parameter:
50167cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
50177cd05799SMatthew G. Knepley 
50187cd05799SMatthew G. Knepley   Level: developer
50197cd05799SMatthew G. Knepley 
5020a1cb98faSBarry Smith   Note:
50217cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
50227cd05799SMatthew G. Knepley 
50231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
50247cd05799SMatthew G. Knepley @*/
5025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
5026d71ae5a4SJacob Faibussowitsch {
502782f516ccSBarry Smith   MPI_Comm comm;
5028552f7358SJed Brown 
5029552f7358SJed Brown   PetscFunctionBegin;
50309566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
50314f572ea9SToby Isaac   PetscAssertPointer(numFaceVertices, 4);
5032552f7358SJed Brown   switch (cellDim) {
5033d71ae5a4SJacob Faibussowitsch   case 0:
5034d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
5035d71ae5a4SJacob Faibussowitsch     break;
5036d71ae5a4SJacob Faibussowitsch   case 1:
5037d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
5038d71ae5a4SJacob Faibussowitsch     break;
5039552f7358SJed Brown   case 2:
5040552f7358SJed Brown     switch (numCorners) {
504119436ca2SJed Brown     case 3:                 /* triangle */
504219436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5043552f7358SJed Brown       break;
504419436ca2SJed Brown     case 4:                 /* quadrilateral */
504519436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5046552f7358SJed Brown       break;
504719436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
504819436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5049552f7358SJed Brown       break;
505019436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
505119436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5052552f7358SJed Brown       break;
5053d71ae5a4SJacob Faibussowitsch     default:
5054d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5055552f7358SJed Brown     }
5056552f7358SJed Brown     break;
5057552f7358SJed Brown   case 3:
5058552f7358SJed Brown     switch (numCorners) {
505919436ca2SJed Brown     case 4:                 /* tetradehdron */
506019436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
5061552f7358SJed Brown       break;
506219436ca2SJed Brown     case 6:                 /* tet cohesive cells */
506319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5064552f7358SJed Brown       break;
506519436ca2SJed Brown     case 8:                 /* hexahedron */
506619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5067552f7358SJed Brown       break;
506819436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
506919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5070552f7358SJed Brown       break;
507119436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
507219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5073552f7358SJed Brown       break;
507419436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
507519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5076552f7358SJed Brown       break;
507719436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
507819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5079552f7358SJed Brown       break;
508019436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
508119436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
5082552f7358SJed Brown       break;
5083d71ae5a4SJacob Faibussowitsch     default:
5084d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5085552f7358SJed Brown     }
5086552f7358SJed Brown     break;
5087d71ae5a4SJacob Faibussowitsch   default:
5088d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
5089552f7358SJed Brown   }
50903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5091552f7358SJed Brown }
5092552f7358SJed Brown 
5093552f7358SJed Brown /*@
5094a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
5095552f7358SJed Brown 
5096552f7358SJed Brown   Not Collective
5097552f7358SJed Brown 
5098aa50250dSMatthew G. Knepley   Input Parameter:
5099a1cb98faSBarry Smith . dm - The `DMPLEX` object
5100552f7358SJed Brown 
5101aa50250dSMatthew G. Knepley   Output Parameter:
5102a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
5103552f7358SJed Brown 
5104552f7358SJed Brown   Level: developer
5105552f7358SJed Brown 
51061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
5107aa50250dSMatthew G. Knepley @*/
5108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
5109d71ae5a4SJacob Faibussowitsch {
5110aa50250dSMatthew G. Knepley   PetscFunctionBegin;
5111aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51124f572ea9SToby Isaac   PetscAssertPointer(depthLabel, 2);
5113c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
51143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5115aa50250dSMatthew G. Knepley }
5116aa50250dSMatthew G. Knepley 
5117aa50250dSMatthew G. Knepley /*@
5118aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
5119aa50250dSMatthew G. Knepley 
5120aa50250dSMatthew G. Knepley   Not Collective
5121aa50250dSMatthew G. Knepley 
5122aa50250dSMatthew G. Knepley   Input Parameter:
5123a1cb98faSBarry Smith . dm - The `DMPLEX` object
5124aa50250dSMatthew G. Knepley 
5125aa50250dSMatthew G. Knepley   Output Parameter:
5126aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
5127aa50250dSMatthew G. Knepley 
5128aa50250dSMatthew G. Knepley   Level: developer
5129552f7358SJed Brown 
5130b1bb481bSMatthew Knepley   Notes:
5131a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
5132a1cb98faSBarry Smith 
5133a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
5134a1cb98faSBarry Smith 
5135dc287ab2SVaclav Hapla   An empty mesh gives -1.
5136b1bb481bSMatthew Knepley 
51371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
5138552f7358SJed Brown @*/
5139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
5140d71ae5a4SJacob Faibussowitsch {
51419f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5142aa50250dSMatthew G. Knepley   DMLabel  label;
5143aa50250dSMatthew G. Knepley   PetscInt d = 0;
5144552f7358SJed Brown 
5145552f7358SJed Brown   PetscFunctionBegin;
5146552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51474f572ea9SToby Isaac   PetscAssertPointer(depth, 2);
51489f4ada15SMatthew G. Knepley   if (mesh->tr) {
51499f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
51509f4ada15SMatthew G. Knepley   } else {
51519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
51529566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
5153552f7358SJed Brown     *depth = d - 1;
51549f4ada15SMatthew G. Knepley   }
51553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5156552f7358SJed Brown }
5157552f7358SJed Brown 
5158552f7358SJed Brown /*@
515920f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
5160552f7358SJed Brown 
5161552f7358SJed Brown   Not Collective
5162552f7358SJed Brown 
5163552f7358SJed Brown   Input Parameters:
5164a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5165570fa34dSVaclav Hapla - depth - The requested depth
5166552f7358SJed Brown 
5167552f7358SJed Brown   Output Parameters:
516820f4b53cSBarry Smith + start - The first point at this `depth`
516920f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
5170552f7358SJed Brown 
5171552f7358SJed Brown   Level: developer
5172552f7358SJed Brown 
5173a1cb98faSBarry Smith   Notes:
5174a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
5175a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
5176a1cb98faSBarry Smith   higher dimension, e.g., "edges".
5177a1cb98faSBarry Smith 
51782827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
5179552f7358SJed Brown @*/
5180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
5181d71ae5a4SJacob Faibussowitsch {
51829f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5183aa50250dSMatthew G. Knepley   DMLabel  label;
518463d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
5185552f7358SJed Brown 
5186552f7358SJed Brown   PetscFunctionBegin;
5187552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51889371c9d4SSatish Balay   if (start) {
51894f572ea9SToby Isaac     PetscAssertPointer(start, 3);
51909371c9d4SSatish Balay     *start = 0;
51919371c9d4SSatish Balay   }
51929371c9d4SSatish Balay   if (end) {
51934f572ea9SToby Isaac     PetscAssertPointer(end, 4);
51949371c9d4SSatish Balay     *end = 0;
51959371c9d4SSatish Balay   }
51969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
51973ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5198570fa34dSVaclav Hapla   if (depth < 0) {
519963d1a920SMatthew G. Knepley     if (start) *start = pStart;
520063d1a920SMatthew G. Knepley     if (end) *end = pEnd;
52013ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5202552f7358SJed Brown   }
52039f4ada15SMatthew G. Knepley   if (mesh->tr) {
52049f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
52059f4ada15SMatthew G. Knepley   } else {
52069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
520728b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5208570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
52099f4ada15SMatthew G. Knepley   }
52103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5211552f7358SJed Brown }
5212552f7358SJed Brown 
5213552f7358SJed Brown /*@
521420f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5215552f7358SJed Brown 
5216552f7358SJed Brown   Not Collective
5217552f7358SJed Brown 
5218552f7358SJed Brown   Input Parameters:
5219a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5220570fa34dSVaclav Hapla - height - The requested height
5221552f7358SJed Brown 
5222552f7358SJed Brown   Output Parameters:
522320f4b53cSBarry Smith + start - The first point at this `height`
522420f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5225552f7358SJed Brown 
5226552f7358SJed Brown   Level: developer
5227552f7358SJed Brown 
5228a1cb98faSBarry Smith   Notes:
5229a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5230a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5231a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5232a1cb98faSBarry Smith 
52332827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5234552f7358SJed Brown @*/
5235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5236d71ae5a4SJacob Faibussowitsch {
5237aa50250dSMatthew G. Knepley   DMLabel  label;
523863d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5239552f7358SJed Brown 
5240552f7358SJed Brown   PetscFunctionBegin;
5241552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52429371c9d4SSatish Balay   if (start) {
52434f572ea9SToby Isaac     PetscAssertPointer(start, 3);
52449371c9d4SSatish Balay     *start = 0;
52459371c9d4SSatish Balay   }
52469371c9d4SSatish Balay   if (end) {
52474f572ea9SToby Isaac     PetscAssertPointer(end, 4);
52489371c9d4SSatish Balay     *end = 0;
52499371c9d4SSatish Balay   }
52509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
52513ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5252570fa34dSVaclav Hapla   if (height < 0) {
525363d1a920SMatthew G. Knepley     if (start) *start = pStart;
525463d1a920SMatthew G. Knepley     if (end) *end = pEnd;
52553ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5256552f7358SJed Brown   }
52579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
525859e4dc13SStefano Zampini   if (label) PetscCall(DMLabelGetNumValues(label, &depth));
525959e4dc13SStefano Zampini   else PetscCall(DMGetDimension(dm, &depth));
526059e4dc13SStefano Zampini   PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed");
526159e4dc13SStefano Zampini   PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end));
52623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5263552f7358SJed Brown }
5264552f7358SJed Brown 
5265ba2698f1SMatthew G. Knepley /*@
526620f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5267ba2698f1SMatthew G. Knepley 
5268ba2698f1SMatthew G. Knepley   Not Collective
5269ba2698f1SMatthew G. Knepley 
5270d8d19677SJose E. Roman   Input Parameters:
5271a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5272ba2698f1SMatthew G. Knepley - point - The point
5273ba2698f1SMatthew G. Knepley 
5274ba2698f1SMatthew G. Knepley   Output Parameter:
527520f4b53cSBarry Smith . depth - The depth of the `point`
5276ba2698f1SMatthew G. Knepley 
5277ba2698f1SMatthew G. Knepley   Level: intermediate
5278ba2698f1SMatthew G. Knepley 
52791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5280ba2698f1SMatthew G. Knepley @*/
5281d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5282d71ae5a4SJacob Faibussowitsch {
5283ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5284ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52854f572ea9SToby Isaac   PetscAssertPointer(depth, 3);
52869566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
52873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5288ba2698f1SMatthew G. Knepley }
5289ba2698f1SMatthew G. Knepley 
5290ba2698f1SMatthew G. Knepley /*@
529120f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
52920c0a32dcSVaclav Hapla 
52930c0a32dcSVaclav Hapla   Not Collective
52940c0a32dcSVaclav Hapla 
5295d8d19677SJose E. Roman   Input Parameters:
5296a1cb98faSBarry Smith + dm    - The `DMPLEX` object
52970c0a32dcSVaclav Hapla - point - The point
52980c0a32dcSVaclav Hapla 
52990c0a32dcSVaclav Hapla   Output Parameter:
530020f4b53cSBarry Smith . height - The height of the `point`
53010c0a32dcSVaclav Hapla 
53020c0a32dcSVaclav Hapla   Level: intermediate
53030c0a32dcSVaclav Hapla 
53041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
53050c0a32dcSVaclav Hapla @*/
5306d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5307d71ae5a4SJacob Faibussowitsch {
53080c0a32dcSVaclav Hapla   PetscInt n, pDepth;
53090c0a32dcSVaclav Hapla 
53100c0a32dcSVaclav Hapla   PetscFunctionBegin;
53110c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53124f572ea9SToby Isaac   PetscAssertPointer(height, 3);
53139566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
53149566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
53150c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
53163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53170c0a32dcSVaclav Hapla }
53180c0a32dcSVaclav Hapla 
53190c0a32dcSVaclav Hapla /*@
5320a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5321ba2698f1SMatthew G. Knepley 
5322ba2698f1SMatthew G. Knepley   Not Collective
5323ba2698f1SMatthew G. Knepley 
5324ba2698f1SMatthew G. Knepley   Input Parameter:
5325a1cb98faSBarry Smith . dm - The `DMPLEX` object
5326ba2698f1SMatthew G. Knepley 
5327ba2698f1SMatthew G. Knepley   Output Parameter:
5328a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5329412e9a14SMatthew G. Knepley 
5330ba2698f1SMatthew G. Knepley   Level: developer
5331ba2698f1SMatthew G. Knepley 
5332a1cb98faSBarry Smith   Note:
5333a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5334a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5335a1cb98faSBarry Smith 
53361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5337ba2698f1SMatthew G. Knepley @*/
5338d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5339d71ae5a4SJacob Faibussowitsch {
5340ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5341ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53424f572ea9SToby Isaac   PetscAssertPointer(celltypeLabel, 2);
53439566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5344ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
53453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5346ba2698f1SMatthew G. Knepley }
5347ba2698f1SMatthew G. Knepley 
5348ba2698f1SMatthew G. Knepley /*@
5349ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5350ba2698f1SMatthew G. Knepley 
5351ba2698f1SMatthew G. Knepley   Not Collective
5352ba2698f1SMatthew G. Knepley 
5353d8d19677SJose E. Roman   Input Parameters:
5354a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5355ba2698f1SMatthew G. Knepley - cell - The cell
5356ba2698f1SMatthew G. Knepley 
5357ba2698f1SMatthew G. Knepley   Output Parameter:
5358ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5359ba2698f1SMatthew G. Knepley 
5360ba2698f1SMatthew G. Knepley   Level: intermediate
5361ba2698f1SMatthew G. Knepley 
53621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5363ba2698f1SMatthew G. Knepley @*/
5364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5365d71ae5a4SJacob Faibussowitsch {
53669f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5367ba2698f1SMatthew G. Knepley   DMLabel  label;
5368ba2698f1SMatthew G. Knepley   PetscInt ct;
5369ba2698f1SMatthew G. Knepley 
5370ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5371ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53724f572ea9SToby Isaac   PetscAssertPointer(celltype, 3);
53739f4ada15SMatthew G. Knepley   if (mesh->tr) {
53749f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
53759f4ada15SMatthew G. Knepley   } else {
537621027e53SStefano Zampini     PetscInt pStart, pEnd;
537721027e53SStefano Zampini 
537821027e53SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL));
537921027e53SStefano Zampini     if (!mesh->cellTypes) { /* XXX remove? optimize? */
538021027e53SStefano Zampini       PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd));
538121027e53SStefano Zampini       PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
538221027e53SStefano Zampini       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
538321027e53SStefano Zampini       for (PetscInt p = pStart; p < pEnd; p++) {
538421027e53SStefano Zampini         PetscCall(DMLabelGetValue(label, p, &ct));
538521027e53SStefano Zampini         mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct;
538621027e53SStefano Zampini       }
538721027e53SStefano Zampini     }
538821027e53SStefano Zampini     *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8;
538921027e53SStefano Zampini     if (PetscDefined(USE_DEBUG)) {
53909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
53919566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, cell, &ct));
539263a3b9bcSJacob Faibussowitsch       PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5393936381afSPierre Jolivet       PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct);
539421027e53SStefano Zampini     }
53959f4ada15SMatthew G. Knepley   }
53963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5397ba2698f1SMatthew G. Knepley }
5398ba2698f1SMatthew G. Knepley 
5399412e9a14SMatthew G. Knepley /*@
5400412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5401412e9a14SMatthew G. Knepley 
5402412e9a14SMatthew G. Knepley   Not Collective
5403412e9a14SMatthew G. Knepley 
5404412e9a14SMatthew G. Knepley   Input Parameters:
5405a1cb98faSBarry Smith + dm       - The `DMPLEX` object
5406412e9a14SMatthew G. Knepley . cell     - The cell
5407412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5408412e9a14SMatthew G. Knepley 
5409a1cb98faSBarry Smith   Level: advanced
5410a1cb98faSBarry Smith 
5411a1cb98faSBarry Smith   Note:
5412a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5413412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5414412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5415db485b19SStefano Zampini   DMCreateLabel(dm, "celltype") before getting or setting any cell types.
5416412e9a14SMatthew G. Knepley 
54171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5418412e9a14SMatthew G. Knepley @*/
5419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5420d71ae5a4SJacob Faibussowitsch {
542121027e53SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
5422412e9a14SMatthew G. Knepley   DMLabel  label;
542321027e53SStefano Zampini   PetscInt pStart, pEnd;
5424412e9a14SMatthew G. Knepley 
5425412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5426412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
542721027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
54289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
54299566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
543021027e53SStefano Zampini   if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
543121027e53SStefano Zampini   mesh->cellTypes[cell - pStart].value_as_uint8 = celltype;
54323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5433412e9a14SMatthew G. Knepley }
5434412e9a14SMatthew G. Knepley 
5435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5436d71ae5a4SJacob Faibussowitsch {
5437efe440bfSMatthew G. Knepley   PetscSection section, s;
5438efe440bfSMatthew G. Knepley   Mat          m;
54393e922f36SToby Isaac   PetscInt     maxHeight;
5440dd4c3f67SMatthew G. Knepley   const char  *prefix;
5441552f7358SJed Brown 
5442552f7358SJed Brown   PetscFunctionBegin;
54439566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5444dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5445dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5446dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
54479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
54489566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
54499566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
54509566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
54519566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
54529566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
54539566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
54549566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
54559566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
54569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
54578f4c458bSMatthew G. Knepley 
54589566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
54599566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5460dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5461dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
54623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5463552f7358SJed Brown }
5464552f7358SJed Brown 
5465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5466d71ae5a4SJacob Faibussowitsch {
54676858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
54686858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5469f19dbd58SToby Isaac 
5470f19dbd58SToby Isaac   PetscFunctionBegin;
5471f19dbd58SToby Isaac   *field = NULL;
54729566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
54739566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
54746858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
54756858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5476f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
54776858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
54786858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5479f19dbd58SToby Isaac   }
54803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5481f19dbd58SToby Isaac }
5482f19dbd58SToby Isaac 
54837cd05799SMatthew G. Knepley /*@C
54847cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
54857cd05799SMatthew G. Knepley 
54867cd05799SMatthew G. Knepley   Not Collective
54877cd05799SMatthew G. Knepley 
54882fe279fdSBarry Smith   Input Parameter:
5489a1cb98faSBarry Smith . dm - The `DMPLEX` object
54907cd05799SMatthew G. Knepley 
54917cd05799SMatthew G. Knepley   Output Parameter:
5492a1cb98faSBarry Smith . section - The `PetscSection` object
54937cd05799SMatthew G. Knepley 
54947cd05799SMatthew G. Knepley   Level: developer
54957cd05799SMatthew G. Knepley 
54961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
54977cd05799SMatthew G. Knepley @*/
5498d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5499d71ae5a4SJacob Faibussowitsch {
5500552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5501552f7358SJed Brown 
5502552f7358SJed Brown   PetscFunctionBegin;
5503552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5504552f7358SJed Brown   if (section) *section = mesh->coneSection;
55053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5506552f7358SJed Brown }
5507552f7358SJed Brown 
55087cd05799SMatthew G. Knepley /*@C
55097cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
55107cd05799SMatthew G. Knepley 
55117cd05799SMatthew G. Knepley   Not Collective
55127cd05799SMatthew G. Knepley 
55132fe279fdSBarry Smith   Input Parameter:
5514a1cb98faSBarry Smith . dm - The `DMPLEX` object
55157cd05799SMatthew G. Knepley 
55167cd05799SMatthew G. Knepley   Output Parameter:
5517a1cb98faSBarry Smith . section - The `PetscSection` object
55187cd05799SMatthew G. Knepley 
55197cd05799SMatthew G. Knepley   Level: developer
55207cd05799SMatthew G. Knepley 
55211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
55227cd05799SMatthew G. Knepley @*/
5523d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5524d71ae5a4SJacob Faibussowitsch {
55258cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
55268cb4d582SMatthew G. Knepley 
55278cb4d582SMatthew G. Knepley   PetscFunctionBegin;
55288cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55298cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
55303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55318cb4d582SMatthew G. Knepley }
55328cb4d582SMatthew G. Knepley 
55337cd05799SMatthew G. Knepley /*@C
55347cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
55357cd05799SMatthew G. Knepley 
55367cd05799SMatthew G. Knepley   Not Collective
55377cd05799SMatthew G. Knepley 
55382fe279fdSBarry Smith   Input Parameter:
5539a1cb98faSBarry Smith . dm - The `DMPLEX` object
55407cd05799SMatthew G. Knepley 
55417cd05799SMatthew G. Knepley   Output Parameter:
55427cd05799SMatthew G. Knepley . cones - The cone for each point
55437cd05799SMatthew G. Knepley 
55447cd05799SMatthew G. Knepley   Level: developer
55457cd05799SMatthew G. Knepley 
55461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
55477cd05799SMatthew G. Knepley @*/
5548d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5549d71ae5a4SJacob Faibussowitsch {
5550552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5551552f7358SJed Brown 
5552552f7358SJed Brown   PetscFunctionBegin;
5553552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5554552f7358SJed Brown   if (cones) *cones = mesh->cones;
55553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5556552f7358SJed Brown }
5557552f7358SJed Brown 
55587cd05799SMatthew G. Knepley /*@C
55597cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
55607cd05799SMatthew G. Knepley 
55617cd05799SMatthew G. Knepley   Not Collective
55627cd05799SMatthew G. Knepley 
55632fe279fdSBarry Smith   Input Parameter:
5564a1cb98faSBarry Smith . dm - The `DMPLEX` object
55657cd05799SMatthew G. Knepley 
55667cd05799SMatthew G. Knepley   Output Parameter:
5567b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
55687cd05799SMatthew G. Knepley 
55697cd05799SMatthew G. Knepley   Level: developer
55707cd05799SMatthew G. Knepley 
5571b5a892a1SMatthew G. Knepley   Notes:
5572a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5573b5a892a1SMatthew G. Knepley 
5574a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5575b5a892a1SMatthew G. Knepley 
55761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
55777cd05799SMatthew G. Knepley @*/
5578d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5579d71ae5a4SJacob Faibussowitsch {
5580552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5581552f7358SJed Brown 
5582552f7358SJed Brown   PetscFunctionBegin;
5583552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5584552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
55853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5586552f7358SJed Brown }
5587552f7358SJed Brown 
5588552f7358SJed Brown /******************************** FEM Support **********************************/
5589552f7358SJed Brown 
5590d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
5591d2b2dc1eSMatthew G. Knepley {
5592d2b2dc1eSMatthew G. Knepley   PetscInt depth;
5593d2b2dc1eSMatthew G. Knepley 
5594d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
5595d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
5596d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS));
5597d2b2dc1eSMatthew G. Knepley   if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS));
5598d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5599d2b2dc1eSMatthew G. Knepley }
5600d2b2dc1eSMatthew G. Knepley 
56015962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS)
56025962854dSMatthew G. Knepley {
56035962854dSMatthew G. Knepley   PetscInt depth;
56045962854dSMatthew G. Knepley 
56055962854dSMatthew G. Knepley   PetscFunctionBegin;
56065962854dSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
56075962854dSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS));
56085962854dSMatthew G. Knepley   if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS));
56095962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
56105962854dSMatthew G. Knepley }
56115962854dSMatthew G. Knepley 
56129e8305c2SJed Brown /*
56139e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
56149e8305c2SJed Brown  representing a line in the section.
56159e8305c2SJed Brown */
5616e327e467SRezgar Shakeri static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous)
5617d71ae5a4SJacob Faibussowitsch {
5618e327e467SRezgar Shakeri   PetscObject  obj;
5619e327e467SRezgar Shakeri   PetscClassId id;
5620e327e467SRezgar Shakeri   PetscFE      fe = NULL;
5621e327e467SRezgar Shakeri 
56229e8305c2SJed Brown   PetscFunctionBeginHot;
56239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5624e327e467SRezgar Shakeri   PetscCall(DMGetField(dm, field, NULL, &obj));
5625e327e467SRezgar Shakeri   PetscCall(PetscObjectGetClassId(obj, &id));
5626e327e467SRezgar Shakeri   if (id == PETSCFE_CLASSID) fe = (PetscFE)obj;
5627e327e467SRezgar Shakeri 
5628e327e467SRezgar Shakeri   if (!fe) {
5629e327e467SRezgar Shakeri     /* Assume the full interpolated mesh is in the chart; lines in particular */
56309e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
56319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
56329e8305c2SJed Brown     *k = *k / *Nc + 1;
5633e327e467SRezgar Shakeri   } else {
5634e327e467SRezgar Shakeri     PetscInt       dual_space_size, dim;
5635e327e467SRezgar Shakeri     PetscDualSpace dual_space;
5636e327e467SRezgar Shakeri     PetscCall(DMGetDimension(dm, &dim));
5637e327e467SRezgar Shakeri     PetscCall(PetscFEGetDualSpace(fe, &dual_space));
5638e327e467SRezgar Shakeri     PetscCall(PetscDualSpaceGetDimension(dual_space, &dual_space_size));
5639e327e467SRezgar Shakeri     *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1;
5640e327e467SRezgar Shakeri     PetscCall(PetscDualSpaceLagrangeGetContinuity(dual_space, continuous));
56419e8305c2SJed Brown   }
56423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56439e8305c2SJed Brown }
56449e8305c2SJed Brown 
5645a4355906SMatthew Knepley /*@
5646bc1eb3faSJed Brown 
5647bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5648bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
564920f4b53cSBarry Smith   section provided (or the section of the `DM`).
5650a4355906SMatthew Knepley 
5651a4355906SMatthew Knepley   Input Parameters:
565220f4b53cSBarry Smith + dm      - The `DM`
565320f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
565420f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5655a4355906SMatthew Knepley 
5656bc1eb3faSJed Brown   Example:
5657bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5658bc1eb3faSJed Brown .vb
5659bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5660bc1eb3faSJed Brown 
5661bc1eb3faSJed Brown   v4 -- e6 -- v3
5662bc1eb3faSJed Brown   |           |
5663bc1eb3faSJed Brown   e7    c0    e8
5664bc1eb3faSJed Brown   |           |
5665bc1eb3faSJed Brown   v1 -- e5 -- v2
5666bc1eb3faSJed Brown .ve
5667bc1eb3faSJed Brown 
5668bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5669bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5670bc1eb3faSJed Brown .vb
5671bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5672bc1eb3faSJed Brown     v1 -> [4]
5673bc1eb3faSJed Brown     ...
5674bc1eb3faSJed Brown     e5 -> [8, 9]
5675bc1eb3faSJed Brown .ve
5676bc1eb3faSJed Brown 
5677bc1eb3faSJed Brown   which corresponds to the dofs
5678bc1eb3faSJed Brown .vb
5679bc1eb3faSJed Brown     6   10  11  7
5680bc1eb3faSJed Brown     13  2   3   15
5681bc1eb3faSJed Brown     12  0   1   14
5682bc1eb3faSJed Brown     4   8   9   5
5683bc1eb3faSJed Brown .ve
5684bc1eb3faSJed Brown 
5685bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5686bc1eb3faSJed Brown .vb
5687bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5688bc1eb3faSJed Brown .ve
5689bc1eb3faSJed Brown 
5690bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5691bc1eb3faSJed Brown .vb
5692bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5693bc1eb3faSJed Brown .ve
5694bc1eb3faSJed Brown 
5695a4355906SMatthew Knepley   Level: developer
5696a4355906SMatthew Knepley 
5697da9ac489SAlbert Cowie   Notes:
5698a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5699a1cb98faSBarry Smith   degree of the basis.
5700a1cb98faSBarry Smith 
5701da9ac489SAlbert Cowie   This is required to run with libCEED.
5702da9ac489SAlbert Cowie 
57031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5704a4355906SMatthew Knepley @*/
5705d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5706d71ae5a4SJacob Faibussowitsch {
57077391a63aSMatthew G. Knepley   DMLabel   label;
5708bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
5709e327e467SRezgar Shakeri   PetscBool continuous = PETSC_TRUE;
57103194fc30SMatthew G. Knepley 
57113194fc30SMatthew G. Knepley   PetscFunctionBegin;
57129566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
57133ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5714a433471fSStefano Zampini   if (point < 0) {
5715a433471fSStefano Zampini     PetscInt sStart, sEnd;
5716a433471fSStefano Zampini 
57179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5718a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5719a433471fSStefano Zampini   }
57209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
57219566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
57229566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
57239371c9d4SSatish Balay   if (depth == 1) {
57249371c9d4SSatish Balay     eStart = point;
57259371c9d4SSatish Balay   } else if (depth == dim) {
57267391a63aSMatthew G. Knepley     const PetscInt *cone;
57277391a63aSMatthew G. Knepley 
57289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5729d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5730d4e6627bSStefano Zampini     else if (dim == 3) {
5731d4e6627bSStefano Zampini       const PetscInt *cone2;
57329566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5733d4e6627bSStefano Zampini       eStart = cone2[0];
573463a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim);
573563a3b9bcSJacob Faibussowitsch   } else PetscCheck(depth < 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim);
5736e327e467SRezgar Shakeri 
57379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5738bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5739bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5740bb197d40SJed Brown     PetscInt *perm;
5741bb197d40SJed Brown 
57423194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5743e327e467SRezgar Shakeri       PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous));
5744bb197d40SJed Brown       size += PetscPowInt(k + 1, d) * Nc;
57453194fc30SMatthew G. Knepley     }
57469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
57473194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5748bb197d40SJed Brown       switch (d) {
5749babf31e0SJed Brown       case 1:
5750e327e467SRezgar Shakeri         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous));
5751babf31e0SJed Brown         /*
5752babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5753babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5754babf31e0SJed Brown          */
5755e327e467SRezgar Shakeri         if (continuous) {
5756babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
57579371c9d4SSatish Balay           for (i = 0; i < k - 1; i++)
57589371c9d4SSatish Balay             for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5759babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5760babf31e0SJed Brown           foffset = offset;
5761e327e467SRezgar Shakeri         } else {
5762e327e467SRezgar Shakeri           for (i = offset; i < size; i++) perm[i] = i - offset + foffset;
5763e327e467SRezgar Shakeri           foffset = offset = size;
5764e327e467SRezgar Shakeri         }
5765babf31e0SJed Brown         break;
576689eabcffSMatthew G. Knepley       case 2:
57673194fc30SMatthew 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} */
5768e327e467SRezgar Shakeri         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous));
57693194fc30SMatthew G. Knepley         /* The SEM order is
57703194fc30SMatthew G. Knepley 
57713194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
577289eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
57733194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
57743194fc30SMatthew G. Knepley          */
5775e327e467SRezgar Shakeri         if (continuous) {
57763194fc30SMatthew G. Knepley           const PetscInt of   = 0;
57773194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
57783194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
57793194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
57803194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
57813194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
57823194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
57833194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
57843194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
57853194fc30SMatthew G. Knepley           PetscInt       o;
57863194fc30SMatthew G. Knepley 
57873194fc30SMatthew G. Knepley           /* bottom */
57883194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
57899371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
57909371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
57913194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
57923194fc30SMatthew G. Knepley           /* middle */
57933194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
57943194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
57959371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
57969371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
57973194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
57983194fc30SMatthew G. Knepley           }
57993194fc30SMatthew G. Knepley           /* top */
58003194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
58019371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
58029371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
58033194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
58043194fc30SMatthew G. Knepley           foffset = offset;
5805e327e467SRezgar Shakeri         } else {
5806e327e467SRezgar Shakeri           for (i = offset; i < size; i++) perm[i] = i - offset + foffset;
5807e327e467SRezgar Shakeri           foffset = offset = size;
58083194fc30SMatthew G. Knepley         }
580989eabcffSMatthew G. Knepley         break;
581089eabcffSMatthew G. Knepley       case 3:
581189eabcffSMatthew G. Knepley         /* The original hex closure is
581289eabcffSMatthew G. Knepley 
581389eabcffSMatthew G. Knepley          {c,
581489eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
581589eabcffSMatthew 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,
581689eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
581789eabcffSMatthew G. Knepley          */
5818e327e467SRezgar Shakeri         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous));
581989eabcffSMatthew G. Knepley         /* The SEM order is
582089eabcffSMatthew G. Knepley          Bottom Slice
582189eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
582289eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
582389eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
582489eabcffSMatthew G. Knepley 
582589eabcffSMatthew G. Knepley          Middle Slice (j)
582689eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
582789eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
582889eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
582989eabcffSMatthew G. Knepley 
583089eabcffSMatthew G. Knepley          Top Slice
583189eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
583289eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
583389eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
583489eabcffSMatthew G. Knepley          */
5835e327e467SRezgar Shakeri         if (continuous) {
583689eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
583789eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
583889eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
583989eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
584089eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
584189eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
584289eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
584389eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
584489eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
584589eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
584689eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
584789eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
584889eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
584989eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
585089eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
585189eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
585289eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
585389eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
585489eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
585589eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
585689eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
585789eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
585889eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
585989eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
586089eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
586189eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
586289eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
586389eabcffSMatthew G. Knepley           PetscInt       o, n;
586489eabcffSMatthew G. Knepley 
586589eabcffSMatthew G. Knepley           /* Bottom Slice */
586689eabcffSMatthew G. Knepley           /*   bottom */
586789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
58689371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
58699371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
587089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
587189eabcffSMatthew G. Knepley           /*   middle */
587289eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
587389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
58749371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
58759371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
58769371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
58779371c9d4SSatish Balay             }
587889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
58793194fc30SMatthew G. Knepley           }
588089eabcffSMatthew G. Knepley           /*   top */
588189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
58829371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
58839371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
588489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
588589eabcffSMatthew G. Knepley 
588689eabcffSMatthew G. Knepley           /* Middle Slice */
588789eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
588889eabcffSMatthew G. Knepley             /*   bottom */
588989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
58909371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
58919371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
589289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
589389eabcffSMatthew G. Knepley             /*   middle */
589489eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
589589eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
58969371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
58979371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
589889eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
589989eabcffSMatthew G. Knepley             }
590089eabcffSMatthew G. Knepley             /*   top */
590189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
59029371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
59039371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
590489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
590589eabcffSMatthew G. Knepley           }
590689eabcffSMatthew G. Knepley 
590789eabcffSMatthew G. Knepley           /* Top Slice */
590889eabcffSMatthew G. Knepley           /*   bottom */
590989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
59109371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
59119371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
591289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
591389eabcffSMatthew G. Knepley           /*   middle */
591489eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
591589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
59169371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
59179371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
591889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
591989eabcffSMatthew G. Knepley           }
592089eabcffSMatthew G. Knepley           /*   top */
592189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
59229371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
59239371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
592489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
592589eabcffSMatthew G. Knepley 
592689eabcffSMatthew G. Knepley           foffset = offset;
5927e327e467SRezgar Shakeri         } else {
5928e327e467SRezgar Shakeri           for (i = offset; i < size; i++) perm[i] = i - offset + foffset;
5929e327e467SRezgar Shakeri           foffset = offset = size;
593089eabcffSMatthew G. Knepley         }
593189eabcffSMatthew G. Knepley         break;
5932d71ae5a4SJacob Faibussowitsch       default:
5933d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
593489eabcffSMatthew G. Knepley       }
593589eabcffSMatthew G. Knepley     }
593663a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
59373194fc30SMatthew G. Knepley     /* Check permutation */
59383194fc30SMatthew G. Knepley     {
59393194fc30SMatthew G. Knepley       PetscInt *check;
59403194fc30SMatthew G. Knepley 
59419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
59421dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
59431dca8a05SBarry Smith         check[i] = -1;
59441dca8a05SBarry Smith         PetscCheck(perm[i] >= 0 && perm[i] < size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid permutation index p[%" PetscInt_FMT "] = %" PetscInt_FMT, i, perm[i]);
59451dca8a05SBarry Smith       }
59463194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
59471dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
59489566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
59493194fc30SMatthew G. Knepley     }
59509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
5951a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5952a05c9aa3SJed Brown       PetscInt *loc_perm;
59539566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
5954a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
5955a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
5956a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
5957a05c9aa3SJed Brown       }
59589566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
5959a05c9aa3SJed Brown     }
5960bb197d40SJed Brown   }
59613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59623194fc30SMatthew G. Knepley }
59633194fc30SMatthew G. Knepley 
5964d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5965d71ae5a4SJacob Faibussowitsch {
5966e071409bSToby Isaac   PetscDS  prob;
5967e071409bSToby Isaac   PetscInt depth, Nf, h;
5968e071409bSToby Isaac   DMLabel  label;
5969e071409bSToby Isaac 
5970e071409bSToby Isaac   PetscFunctionBeginHot;
59719566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5972e071409bSToby Isaac   Nf      = prob->Nf;
5973e071409bSToby Isaac   label   = dm->depthLabel;
5974e071409bSToby Isaac   *dspace = NULL;
5975e071409bSToby Isaac   if (field < Nf) {
5976e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5977e071409bSToby Isaac 
5978e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5979e071409bSToby Isaac       PetscDualSpace dsp;
5980e071409bSToby Isaac 
59819566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
59829566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
59839566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
5984e071409bSToby Isaac       h = depth - 1 - h;
5985e071409bSToby Isaac       if (h) {
59869566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
5987e071409bSToby Isaac       } else {
5988e071409bSToby Isaac         *dspace = dsp;
5989e071409bSToby Isaac       }
5990e071409bSToby Isaac     }
5991e071409bSToby Isaac   }
59923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5993e071409bSToby Isaac }
5994e071409bSToby Isaac 
5995d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5996d71ae5a4SJacob Faibussowitsch {
599728351e22SJed Brown   PetscScalar       *array;
599828351e22SJed Brown   const PetscScalar *vArray;
5999d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
60001a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
6001552f7358SJed Brown 
60021b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
60039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
60049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
60059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
60069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
60073f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
60089df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
60099df71ca4SMatthew G. Knepley       PetscInt dof;
6010d9917b9dSMatthew G. Knepley 
60119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
60129df71ca4SMatthew G. Knepley       size += dof;
60139df71ca4SMatthew G. Knepley     }
60149df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
60159df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
60162a3aaacfSMatthew G. Knepley       PetscInt       dof;
60175a1bb5cfSMatthew G. Knepley 
60185a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
60199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
60205a1bb5cfSMatthew G. Knepley       size += dof;
60215a1bb5cfSMatthew G. Knepley     }
60223f7cbbe7SMatthew G. Knepley     if (!values) {
60233f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
60243ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
60253f7cbbe7SMatthew G. Knepley     }
60269566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
6027982e9ed1SMatthew G. Knepley   } else {
6028982e9ed1SMatthew G. Knepley     array = *values;
6029982e9ed1SMatthew G. Knepley   }
60309df71ca4SMatthew G. Knepley   size = 0;
603128351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
60329df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
60339df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
603428351e22SJed Brown     const PetscScalar *varr;
6035d9917b9dSMatthew G. Knepley 
60369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
60379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
60389df71ca4SMatthew G. Knepley     varr = &vArray[off];
6039ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
60409df71ca4SMatthew G. Knepley     size += dof;
60419df71ca4SMatthew G. Knepley   }
60429df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
60439df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
60449df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
60455a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
604628351e22SJed Brown     const PetscScalar *varr;
60475a1bb5cfSMatthew G. Knepley 
604852ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
60499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
60509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
60515a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
60525a1bb5cfSMatthew G. Knepley     if (o >= 0) {
6053ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
60545a1bb5cfSMatthew G. Knepley     } else {
6055ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
60565a1bb5cfSMatthew G. Knepley     }
60579df71ca4SMatthew G. Knepley     size += dof;
60585a1bb5cfSMatthew G. Knepley   }
605928351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
60609df71ca4SMatthew G. Knepley   if (!*values) {
60615a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
60625a1bb5cfSMatthew G. Knepley     *values = array;
60639df71ca4SMatthew G. Knepley   } else {
606463a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
60658c312ff3SMatthew G. Knepley     *csize = size;
60669df71ca4SMatthew G. Knepley   }
60673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60685a1bb5cfSMatthew G. Knepley }
6069d9917b9dSMatthew G. Knepley 
607027f02ce8SMatthew G. Knepley /* Compress out points not in the section */
6071d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
6072d71ae5a4SJacob Faibussowitsch {
607327f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
607427f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
607527f02ce8SMatthew G. Knepley 
60769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
607727f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
607827f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
607927f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
608027f02ce8SMatthew G. Knepley       points[q * 2]     = r;
608127f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
608227f02ce8SMatthew G. Knepley       ++q;
608327f02ce8SMatthew G. Knepley     }
608427f02ce8SMatthew G. Knepley   }
608527f02ce8SMatthew G. Knepley   *numPoints = q;
60863ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
608727f02ce8SMatthew G. Knepley }
608827f02ce8SMatthew G. Knepley 
608997529cf3SJed Brown /* Compressed closure does not apply closure permutation */
609007218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6091d71ae5a4SJacob Faibussowitsch {
609227f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
6093923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
6094923c78e0SToby Isaac 
6095923c78e0SToby Isaac   PetscFunctionBeginHot;
60969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
609707218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
6098923c78e0SToby Isaac     PetscInt dof, off;
6099923c78e0SToby Isaac 
61009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
61019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
61029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
6103923c78e0SToby Isaac     np  = dof / 2;
6104923c78e0SToby Isaac     pts = (PetscInt *)&cla[off];
610527f02ce8SMatthew G. Knepley   } else {
610607218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
61079566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
6108923c78e0SToby Isaac   }
6109923c78e0SToby Isaac   *numPoints = np;
6110923c78e0SToby Isaac   *points    = pts;
6111923c78e0SToby Isaac   *clp       = cla;
61123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6113923c78e0SToby Isaac }
6114923c78e0SToby Isaac 
6115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6116d71ae5a4SJacob Faibussowitsch {
6117923c78e0SToby Isaac   PetscFunctionBeginHot;
6118923c78e0SToby Isaac   if (!*clPoints) {
61199566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
6120923c78e0SToby Isaac   } else {
61219566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
6122923c78e0SToby Isaac   }
6123923c78e0SToby Isaac   *numPoints = 0;
6124923c78e0SToby Isaac   *points    = NULL;
6125923c78e0SToby Isaac   *clSec     = NULL;
6126923c78e0SToby Isaac   *clPoints  = NULL;
6127923c78e0SToby Isaac   *clp       = NULL;
61283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6129923c78e0SToby Isaac }
6130923c78e0SToby Isaac 
6131d71ae5a4SJacob 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[])
6132d71ae5a4SJacob Faibussowitsch {
61331a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
613497e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
613597e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
61361a271a75SMatthew G. Knepley 
61371a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6138fe02ba77SJed Brown   *size = 0;
61399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
614097e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
614197e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
614297e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
614397e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
61441a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
61451a271a75SMatthew G. Knepley     const PetscScalar *varr;
61461a271a75SMatthew G. Knepley 
61479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
61489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
61491a271a75SMatthew G. Knepley     varr = &vArray[off];
615097e99dd9SToby Isaac     if (clperm) {
615197e99dd9SToby Isaac       if (perm) {
615297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
61531a271a75SMatthew G. Knepley       } else {
615497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
615597e99dd9SToby Isaac       }
615697e99dd9SToby Isaac       if (flip) {
615797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
615897e99dd9SToby Isaac       }
615997e99dd9SToby Isaac     } else {
616097e99dd9SToby Isaac       if (perm) {
616197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
616297e99dd9SToby Isaac       } else {
616397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
616497e99dd9SToby Isaac       }
616597e99dd9SToby Isaac       if (flip) {
616697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
61671a271a75SMatthew G. Knepley       }
61681a271a75SMatthew G. Knepley     }
616997e99dd9SToby Isaac     offset += dof;
617097e99dd9SToby Isaac   }
61719566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
61721a271a75SMatthew G. Knepley   *size = offset;
61733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61741a271a75SMatthew G. Knepley }
61751a271a75SMatthew G. Knepley 
6176d71ae5a4SJacob 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[])
6177d71ae5a4SJacob Faibussowitsch {
61781a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
61791a271a75SMatthew G. Knepley 
61801a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6181fe02ba77SJed Brown   *size = 0;
61821a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
618397e99dd9SToby Isaac     PetscInt            p;
618497e99dd9SToby Isaac     const PetscInt    **perms = NULL;
618597e99dd9SToby Isaac     const PetscScalar **flips = NULL;
61861a271a75SMatthew G. Knepley 
61879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
618897e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
618997e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
619097e99dd9SToby Isaac       PetscInt           fdof, foff, b;
61911a271a75SMatthew G. Knepley       const PetscScalar *varr;
619297e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
619397e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
61941a271a75SMatthew G. Knepley 
61959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
61969566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
61971a271a75SMatthew G. Knepley       varr = &vArray[foff];
619897e99dd9SToby Isaac       if (clperm) {
61999371c9d4SSatish Balay         if (perm) {
6200ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
62011a271a75SMatthew G. Knepley         } else {
6202ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
62039371c9d4SSatish Balay         }
62049371c9d4SSatish Balay         if (flip) {
6205ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
62069371c9d4SSatish Balay         }
62079371c9d4SSatish Balay       } else {
62089371c9d4SSatish Balay         if (perm) {
6209ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
62109371c9d4SSatish Balay         } else {
6211ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
62129371c9d4SSatish Balay         }
62139371c9d4SSatish Balay         if (flip) {
6214ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
62159371c9d4SSatish Balay         }
62161a271a75SMatthew G. Knepley       }
621797e99dd9SToby Isaac       offset += fdof;
62181a271a75SMatthew G. Knepley     }
62199566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
62201a271a75SMatthew G. Knepley   }
62211a271a75SMatthew G. Knepley   *size = offset;
62223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62231a271a75SMatthew G. Knepley }
62241a271a75SMatthew G. Knepley 
6225e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
622607218a29SMatthew G. Knepley {
622707218a29SMatthew G. Knepley   PetscSection    clSection;
622807218a29SMatthew G. Knepley   IS              clPoints;
622907218a29SMatthew G. Knepley   PetscInt       *points = NULL;
6230e8e188d2SZach Atkins   const PetscInt *clp, *perm = NULL;
623107218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
623207218a29SMatthew G. Knepley 
623307218a29SMatthew G. Knepley   PetscFunctionBeginHot;
623407218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
623507218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
623607218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6237e8e188d2SZach Atkins   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
623807218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
623907218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
624007218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
624107218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
624207218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
624307218a29SMatthew G. Knepley   }
624407218a29SMatthew G. Knepley   /* Get points */
624507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
624607218a29SMatthew G. Knepley   /* Get sizes */
624707218a29SMatthew G. Knepley   asize = 0;
624807218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
624907218a29SMatthew G. Knepley     PetscInt dof;
625007218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
625107218a29SMatthew G. Knepley     asize += dof;
625207218a29SMatthew G. Knepley   }
625307218a29SMatthew G. Knepley   if (values) {
625407218a29SMatthew G. Knepley     const PetscScalar *vArray;
625507218a29SMatthew G. Knepley     PetscInt           size;
625607218a29SMatthew G. Knepley 
625707218a29SMatthew G. Knepley     if (*values) {
625807218a29SMatthew G. Knepley       PetscCheck(*csize >= asize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %" PetscInt_FMT " not sufficient to hold closure size %" PetscInt_FMT, *csize, asize);
625907218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
6260e8e188d2SZach Atkins     if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
626107218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
626207218a29SMatthew G. Knepley     /* Get values */
626307218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
626407218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
626507218a29SMatthew G. Knepley     PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
626607218a29SMatthew G. Knepley     /* Cleanup array */
626707218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
626807218a29SMatthew G. Knepley   }
626907218a29SMatthew G. Knepley   if (csize) *csize = asize;
627007218a29SMatthew G. Knepley   /* Cleanup points */
627107218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
627207218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
627307218a29SMatthew G. Knepley }
627407218a29SMatthew G. Knepley 
6275552f7358SJed Brown /*@C
6276552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6277552f7358SJed Brown 
6278552f7358SJed Brown   Not collective
6279552f7358SJed Brown 
6280552f7358SJed Brown   Input Parameters:
6281a1cb98faSBarry Smith + dm      - The `DM`
628220f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6283552f7358SJed Brown . v       - The local vector
6284a1cb98faSBarry Smith - point   - The point in the `DM`
6285552f7358SJed Brown 
62866b867d5aSJose E. Roman   Input/Output Parameters:
628720f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
628820f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
628920f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
629022c1ee49SMatthew G. Knepley 
6291552f7358SJed Brown   Level: intermediate
6292552f7358SJed Brown 
6293a1cb98faSBarry Smith   Notes:
629420f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6295a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6296a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6297a1cb98faSBarry Smith 
6298a1cb98faSBarry Smith   A typical use could be
6299a1cb98faSBarry Smith .vb
6300a1cb98faSBarry Smith    values = NULL;
6301a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6302a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6303a1cb98faSBarry Smith      <Compute on closure>
6304a1cb98faSBarry Smith    }
6305a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6306a1cb98faSBarry Smith .ve
6307a1cb98faSBarry Smith   or
6308a1cb98faSBarry Smith .vb
6309a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6310a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6311a1cb98faSBarry Smith      clSize = clMaxSize;
6312a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6313a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6314a1cb98faSBarry Smith        <Compute on closure>
6315a1cb98faSBarry Smith      }
6316a1cb98faSBarry Smith    }
6317a1cb98faSBarry Smith    PetscFree(values);
6318a1cb98faSBarry Smith .ve
6319a1cb98faSBarry Smith 
632060225df5SJacob Faibussowitsch   Fortran Notes:
632120f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6322a1cb98faSBarry Smith 
63231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6324552f7358SJed Brown @*/
6325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6326d71ae5a4SJacob Faibussowitsch {
6327d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
6328e8e188d2SZach Atkins   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values));
63293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6330552f7358SJed Brown }
6331552f7358SJed Brown 
6332d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6333d71ae5a4SJacob Faibussowitsch {
6334e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6335e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6336e5c487bfSMatthew G. Knepley   IS                 clPoints;
6337e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6338e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6339e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6340c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6341c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6342e5c487bfSMatthew G. Knepley 
6343e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6344e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63459566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6346e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6347e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
63489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
63499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
63509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6351e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
63529566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
63533ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6354e5c487bfSMatthew G. Knepley   }
6355e5c487bfSMatthew G. Knepley   /* Get points */
635607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6357c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6358c459fbc1SJed Brown     PetscInt dof;
63599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6360c459fbc1SJed Brown     clsize += dof;
6361c459fbc1SJed Brown   }
63629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6363e5c487bfSMatthew G. Knepley   /* Filter points */
6364e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6365e5c487bfSMatthew G. Knepley     PetscInt dep;
6366e5c487bfSMatthew G. Knepley 
63679566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6368e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6369e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6370e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6371e5c487bfSMatthew G. Knepley     ++Np;
6372e5c487bfSMatthew G. Knepley   }
6373e5c487bfSMatthew G. Knepley   /* Get array */
6374e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6375e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6376e5c487bfSMatthew G. Knepley 
6377e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
63789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6379e5c487bfSMatthew G. Knepley       asize += dof;
6380e5c487bfSMatthew G. Knepley     }
6381e5c487bfSMatthew G. Knepley     if (!values) {
63829566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6383e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
63843ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6385e5c487bfSMatthew G. Knepley     }
63869566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6387e5c487bfSMatthew G. Knepley   } else {
6388e5c487bfSMatthew G. Knepley     array = *values;
6389e5c487bfSMatthew G. Knepley   }
63909566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6391e5c487bfSMatthew G. Knepley   /* Get values */
63929566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
63939566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6394e5c487bfSMatthew G. Knepley   /* Cleanup points */
63959566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6396e5c487bfSMatthew G. Knepley   /* Cleanup array */
63979566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6398e5c487bfSMatthew G. Knepley   if (!*values) {
6399e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6400e5c487bfSMatthew G. Knepley     *values = array;
6401e5c487bfSMatthew G. Knepley   } else {
640263a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6403e5c487bfSMatthew G. Knepley     *csize = size;
6404e5c487bfSMatthew G. Knepley   }
64053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6406e5c487bfSMatthew G. Knepley }
6407e5c487bfSMatthew G. Knepley 
6408552f7358SJed Brown /*@C
6409552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6410552f7358SJed Brown 
6411552f7358SJed Brown   Not collective
6412552f7358SJed Brown 
6413552f7358SJed Brown   Input Parameters:
6414a1cb98faSBarry Smith + dm      - The `DM`
641520f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6416552f7358SJed Brown . v       - The local vector
6417a1cb98faSBarry Smith . point   - The point in the `DM`
641820f4b53cSBarry Smith . csize   - The number of values in the closure, or `NULL`
6419552f7358SJed Brown - values  - The array of values, which is a borrowed array and should not be freed
6420552f7358SJed Brown 
6421552f7358SJed Brown   Level: intermediate
6422552f7358SJed Brown 
6423a1cb98faSBarry Smith   Note:
642420f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6425a1cb98faSBarry Smith 
642660225df5SJacob Faibussowitsch   Fortran Notes:
642720f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6428a1cb98faSBarry Smith 
64291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6430552f7358SJed Brown @*/
6431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6432d71ae5a4SJacob Faibussowitsch {
6433552f7358SJed Brown   PetscInt size = 0;
6434552f7358SJed Brown 
6435552f7358SJed Brown   PetscFunctionBegin;
6436552f7358SJed Brown   /* Should work without recalculating size */
64379566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6438c9fdaa05SMatthew G. Knepley   *values = NULL;
64393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6440552f7358SJed Brown }
6441552f7358SJed Brown 
6442d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6443d71ae5a4SJacob Faibussowitsch {
64449371c9d4SSatish Balay   *x += y;
64459371c9d4SSatish Balay }
6446d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6447d71ae5a4SJacob Faibussowitsch {
64489371c9d4SSatish Balay   *x = y;
64499371c9d4SSatish Balay }
6450552f7358SJed Brown 
6451d71ae5a4SJacob 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[])
6452d71ae5a4SJacob Faibussowitsch {
6453552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6454552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6455552f7358SJed Brown   PetscScalar    *a;
6456552f7358SJed Brown   PetscInt        off, cind = 0, k;
6457552f7358SJed Brown 
6458552f7358SJed Brown   PetscFunctionBegin;
64599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
64609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6461552f7358SJed Brown   a = &array[off];
6462552f7358SJed Brown   if (!cdof || setBC) {
646397e99dd9SToby Isaac     if (clperm) {
64649371c9d4SSatish Balay       if (perm) {
6465ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6466552f7358SJed Brown       } else {
6467ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
64689371c9d4SSatish Balay       }
64699371c9d4SSatish Balay     } else {
64709371c9d4SSatish Balay       if (perm) {
6471ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
64729371c9d4SSatish Balay       } else {
6473ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
64749371c9d4SSatish Balay       }
6475552f7358SJed Brown     }
6476552f7358SJed Brown   } else {
64779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
647897e99dd9SToby Isaac     if (clperm) {
64799371c9d4SSatish Balay       if (perm) {
64809371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
64819371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
64829371c9d4SSatish Balay             ++cind;
64839371c9d4SSatish Balay             continue;
64849371c9d4SSatish Balay           }
648597e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6486552f7358SJed Brown         }
6487552f7358SJed Brown       } else {
6488552f7358SJed Brown         for (k = 0; k < dof; ++k) {
64899371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
64909371c9d4SSatish Balay             ++cind;
64919371c9d4SSatish Balay             continue;
64929371c9d4SSatish Balay           }
649397e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
649497e99dd9SToby Isaac         }
649597e99dd9SToby Isaac       }
649697e99dd9SToby Isaac     } else {
649797e99dd9SToby Isaac       if (perm) {
649897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
64999371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
65009371c9d4SSatish Balay             ++cind;
65019371c9d4SSatish Balay             continue;
65029371c9d4SSatish Balay           }
650397e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
650497e99dd9SToby Isaac         }
650597e99dd9SToby Isaac       } else {
650697e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
65079371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
65089371c9d4SSatish Balay             ++cind;
65099371c9d4SSatish Balay             continue;
65109371c9d4SSatish Balay           }
651197e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
651297e99dd9SToby Isaac         }
6513552f7358SJed Brown       }
6514552f7358SJed Brown     }
6515552f7358SJed Brown   }
65163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6517552f7358SJed Brown }
6518552f7358SJed Brown 
6519d71ae5a4SJacob 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[])
6520d71ae5a4SJacob Faibussowitsch {
6521a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6522a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6523a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6524a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6525a5e93ea8SMatthew G. Knepley 
6526a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
65279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
65289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6529a5e93ea8SMatthew G. Knepley   a = &array[off];
6530a5e93ea8SMatthew G. Knepley   if (cdof) {
65319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
653297e99dd9SToby Isaac     if (clperm) {
653397e99dd9SToby Isaac       if (perm) {
6534a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6535a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
653697e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
653797e99dd9SToby Isaac             cind++;
6538a5e93ea8SMatthew G. Knepley           }
6539a5e93ea8SMatthew G. Knepley         }
6540a5e93ea8SMatthew G. Knepley       } else {
6541a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6542a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
654397e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
654497e99dd9SToby Isaac             cind++;
654597e99dd9SToby Isaac           }
654697e99dd9SToby Isaac         }
654797e99dd9SToby Isaac       }
654897e99dd9SToby Isaac     } else {
654997e99dd9SToby Isaac       if (perm) {
655097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
655197e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
655297e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
655397e99dd9SToby Isaac             cind++;
655497e99dd9SToby Isaac           }
655597e99dd9SToby Isaac         }
655697e99dd9SToby Isaac       } else {
655797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
655897e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
655997e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
656097e99dd9SToby Isaac             cind++;
656197e99dd9SToby Isaac           }
6562a5e93ea8SMatthew G. Knepley         }
6563a5e93ea8SMatthew G. Knepley       }
6564a5e93ea8SMatthew G. Knepley     }
6565a5e93ea8SMatthew G. Knepley   }
65663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6567a5e93ea8SMatthew G. Knepley }
6568a5e93ea8SMatthew G. Knepley 
6569d71ae5a4SJacob 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[])
6570d71ae5a4SJacob Faibussowitsch {
6571552f7358SJed Brown   PetscScalar    *a;
65721a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
65731a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
657497e99dd9SToby Isaac   PetscInt        cind = 0, b;
6575552f7358SJed Brown 
6576552f7358SJed Brown   PetscFunctionBegin;
65779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
65789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
65799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
65801a271a75SMatthew G. Knepley   a = &array[foff];
6581552f7358SJed Brown   if (!fcdof || setBC) {
658297e99dd9SToby Isaac     if (clperm) {
65839371c9d4SSatish Balay       if (perm) {
6584ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6585552f7358SJed Brown       } else {
6586ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
65879371c9d4SSatish Balay       }
65889371c9d4SSatish Balay     } else {
65899371c9d4SSatish Balay       if (perm) {
6590ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
65919371c9d4SSatish Balay       } else {
6592ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
65939371c9d4SSatish Balay       }
6594552f7358SJed Brown     }
6595552f7358SJed Brown   } else {
65969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
659797e99dd9SToby Isaac     if (clperm) {
659897e99dd9SToby Isaac       if (perm) {
659997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
66009371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
66019371c9d4SSatish Balay             ++cind;
66029371c9d4SSatish Balay             continue;
66039371c9d4SSatish Balay           }
660497e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6605552f7358SJed Brown         }
6606552f7358SJed Brown       } else {
660797e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
66089371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
66099371c9d4SSatish Balay             ++cind;
66109371c9d4SSatish Balay             continue;
66119371c9d4SSatish Balay           }
661297e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
661397e99dd9SToby Isaac         }
661497e99dd9SToby Isaac       }
661597e99dd9SToby Isaac     } else {
661697e99dd9SToby Isaac       if (perm) {
661797e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
66189371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
66199371c9d4SSatish Balay             ++cind;
66209371c9d4SSatish Balay             continue;
66219371c9d4SSatish Balay           }
662297e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
662397e99dd9SToby Isaac         }
662497e99dd9SToby Isaac       } else {
662597e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
66269371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
66279371c9d4SSatish Balay             ++cind;
66289371c9d4SSatish Balay             continue;
66299371c9d4SSatish Balay           }
663097e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6631552f7358SJed Brown         }
6632552f7358SJed Brown       }
6633552f7358SJed Brown     }
6634552f7358SJed Brown   }
66351a271a75SMatthew G. Knepley   *offset += fdof;
66363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6637552f7358SJed Brown }
6638552f7358SJed Brown 
6639d71ae5a4SJacob 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[])
6640d71ae5a4SJacob Faibussowitsch {
6641a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
66421a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
66431a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66445da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6645ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6646a5e93ea8SMatthew G. Knepley 
6647a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
66489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
66499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
66509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
66519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
66521a271a75SMatthew G. Knepley   a = &array[foff];
6653a5e93ea8SMatthew G. Knepley   if (fcdof) {
6654ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
66559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
665697e99dd9SToby Isaac     if (clperm) {
665797e99dd9SToby Isaac       if (perm) {
6658ba322698SMatthew G. Knepley         if (comps) {
6659ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6660ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
66619371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
66629371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
66639371c9d4SSatish Balay               ncSet = PETSC_TRUE;
66649371c9d4SSatish Balay             }
66659371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
66669371c9d4SSatish Balay               ++cind;
66679371c9d4SSatish Balay               fcSet = PETSC_TRUE;
66689371c9d4SSatish Balay             }
6669ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6670ba322698SMatthew G. Knepley           }
6671ba322698SMatthew G. Knepley         } else {
667297e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
667397e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
667497e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6675a5e93ea8SMatthew G. Knepley               ++cind;
6676a5e93ea8SMatthew G. Knepley             }
6677a5e93ea8SMatthew G. Knepley           }
6678ba322698SMatthew G. Knepley         }
6679ba322698SMatthew G. Knepley       } else {
6680ba322698SMatthew G. Knepley         if (comps) {
6681ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6682ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
66839371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
66849371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
66859371c9d4SSatish Balay               ncSet = PETSC_TRUE;
66869371c9d4SSatish Balay             }
66879371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
66889371c9d4SSatish Balay               ++cind;
66899371c9d4SSatish Balay               fcSet = PETSC_TRUE;
66909371c9d4SSatish Balay             }
6691ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6692ba322698SMatthew G. Knepley           }
6693a5e93ea8SMatthew G. Knepley         } else {
669497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
669597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
669697e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
669797e99dd9SToby Isaac               ++cind;
669897e99dd9SToby Isaac             }
669997e99dd9SToby Isaac           }
670097e99dd9SToby Isaac         }
6701ba322698SMatthew G. Knepley       }
670297e99dd9SToby Isaac     } else {
670397e99dd9SToby Isaac       if (perm) {
6704ba322698SMatthew G. Knepley         if (comps) {
6705ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6706ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
67079371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
67089371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
67099371c9d4SSatish Balay               ncSet = PETSC_TRUE;
67109371c9d4SSatish Balay             }
67119371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
67129371c9d4SSatish Balay               ++cind;
67139371c9d4SSatish Balay               fcSet = PETSC_TRUE;
67149371c9d4SSatish Balay             }
6715ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6716ba322698SMatthew G. Knepley           }
6717ba322698SMatthew G. Knepley         } else {
671897e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
671997e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
672097e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
672197e99dd9SToby Isaac               ++cind;
672297e99dd9SToby Isaac             }
672397e99dd9SToby Isaac           }
6724ba322698SMatthew G. Knepley         }
6725ba322698SMatthew G. Knepley       } else {
6726ba322698SMatthew G. Knepley         if (comps) {
6727ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6728ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
67299371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
67309371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
67319371c9d4SSatish Balay               ncSet = PETSC_TRUE;
67329371c9d4SSatish Balay             }
67339371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
67349371c9d4SSatish Balay               ++cind;
67359371c9d4SSatish Balay               fcSet = PETSC_TRUE;
67369371c9d4SSatish Balay             }
6737ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6738ba322698SMatthew G. Knepley           }
673997e99dd9SToby Isaac         } else {
674097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
674197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
674297e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6743a5e93ea8SMatthew G. Knepley               ++cind;
6744a5e93ea8SMatthew G. Knepley             }
6745a5e93ea8SMatthew G. Knepley           }
6746a5e93ea8SMatthew G. Knepley         }
6747a5e93ea8SMatthew G. Knepley       }
6748a5e93ea8SMatthew G. Knepley     }
6749ba322698SMatthew G. Knepley   }
67501a271a75SMatthew G. Knepley   *offset += fdof;
67513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6752a5e93ea8SMatthew G. Knepley }
6753a5e93ea8SMatthew G. Knepley 
6754d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6755d71ae5a4SJacob Faibussowitsch {
6756552f7358SJed Brown   PetscScalar    *array;
67571b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
67581b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6759552f7358SJed Brown 
67601b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
67619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
67629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
67639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
67649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
67659566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6766b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6767b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6768b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6769b6ebb6e6SMatthew G. Knepley 
67709371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
67719371c9d4SSatish Balay       dof = 0;
67729371c9d4SSatish Balay       continue;
67739371c9d4SSatish Balay     }
67749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6775b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6776b6ebb6e6SMatthew G. Knepley     {
6777b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6778b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6779b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6780b6ebb6e6SMatthew G. Knepley 
67819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
67829566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6783b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6784b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6785b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6786ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6787b6ebb6e6SMatthew G. Knepley         } else {
6788ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6789b6ebb6e6SMatthew G. Knepley         }
6790b6ebb6e6SMatthew G. Knepley       } else {
67919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6792b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6793b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
67949371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
67959371c9d4SSatish Balay               ++cind;
67969371c9d4SSatish Balay               continue;
67979371c9d4SSatish Balay             }
6798b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6799b6ebb6e6SMatthew G. Knepley           }
6800b6ebb6e6SMatthew G. Knepley         } else {
6801b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
68029371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
68039371c9d4SSatish Balay               ++cind;
68049371c9d4SSatish Balay               continue;
68059371c9d4SSatish Balay             }
6806b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6807b6ebb6e6SMatthew G. Knepley           }
6808b6ebb6e6SMatthew G. Knepley         }
6809b6ebb6e6SMatthew G. Knepley       }
6810b6ebb6e6SMatthew G. Knepley     }
6811b6ebb6e6SMatthew G. Knepley   }
68129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
68133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6814b6ebb6e6SMatthew G. Knepley }
68151b406b76SMatthew G. Knepley 
68161b406b76SMatthew G. Knepley /*@C
681720f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
68181b406b76SMatthew G. Knepley 
68191b406b76SMatthew G. Knepley   Not collective
68201b406b76SMatthew G. Knepley 
68211b406b76SMatthew G. Knepley   Input Parameters:
6822a1cb98faSBarry Smith + dm      - The `DM`
682320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
68241b406b76SMatthew G. Knepley . v       - The local vector
682520f4b53cSBarry Smith . point   - The point in the `DM`
68261b406b76SMatthew G. Knepley . values  - The array of values
6827a1cb98faSBarry Smith - mode    - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6828a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
68291b406b76SMatthew G. Knepley 
68301b406b76SMatthew G. Knepley   Level: intermediate
68311b406b76SMatthew G. Knepley 
68321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
68331b406b76SMatthew G. Knepley @*/
6834d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6835d71ae5a4SJacob Faibussowitsch {
68361b406b76SMatthew G. Knepley   PetscSection    clSection;
68371b406b76SMatthew G. Knepley   IS              clPoints;
68381b406b76SMatthew G. Knepley   PetscScalar    *array;
68391b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
684027f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6841c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
68421b406b76SMatthew G. Knepley 
68431a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
68441b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68459566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
68461a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
68471a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
68489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
68499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
68501b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
68519566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
68523ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
68531b406b76SMatthew G. Knepley   }
68541a271a75SMatthew G. Knepley   /* Get points */
685507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6856c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6857c459fbc1SJed Brown     PetscInt dof;
68589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6859c459fbc1SJed Brown     clsize += dof;
6860c459fbc1SJed Brown   }
68619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
68621a271a75SMatthew G. Knepley   /* Get array */
68639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
68641a271a75SMatthew G. Knepley   /* Get values */
6865ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
686697e99dd9SToby Isaac     PetscInt offset = 0, f;
6867552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
686897e99dd9SToby Isaac       const PetscInt    **perms = NULL;
686997e99dd9SToby Isaac       const PetscScalar **flips = NULL;
687097e99dd9SToby Isaac 
68719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6872552f7358SJed Brown       switch (mode) {
6873552f7358SJed Brown       case INSERT_VALUES:
687497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
687597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
687697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
687797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
68783ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
68799371c9d4SSatish Balay         }
68809371c9d4SSatish Balay         break;
6881552f7358SJed Brown       case INSERT_ALL_VALUES:
688297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
688397e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
688497e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
688597e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
68863ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
68879371c9d4SSatish Balay         }
68889371c9d4SSatish Balay         break;
6889a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
689097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
689197e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
689297e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
689397e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
68943ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
68959371c9d4SSatish Balay         }
68969371c9d4SSatish Balay         break;
6897552f7358SJed Brown       case ADD_VALUES:
689897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
689997e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
690097e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
690197e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
69023ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
69039371c9d4SSatish Balay         }
69049371c9d4SSatish Balay         break;
6905552f7358SJed Brown       case ADD_ALL_VALUES:
690697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
690797e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
690897e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
690997e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
69103ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
69119371c9d4SSatish Balay         }
69129371c9d4SSatish Balay         break;
6913304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
691497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
691597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
691697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
691797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
69183ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
69199371c9d4SSatish Balay         }
69209371c9d4SSatish Balay         break;
6921d71ae5a4SJacob Faibussowitsch       default:
6922d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6923552f7358SJed Brown       }
69249566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
69251a271a75SMatthew G. Knepley     }
6926552f7358SJed Brown   } else {
69271a271a75SMatthew G. Knepley     PetscInt            dof, off;
692897e99dd9SToby Isaac     const PetscInt    **perms = NULL;
692997e99dd9SToby Isaac     const PetscScalar **flips = NULL;
69301a271a75SMatthew G. Knepley 
69319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
6932552f7358SJed Brown     switch (mode) {
6933552f7358SJed Brown     case INSERT_VALUES:
693497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
693597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
693697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
693797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
69389566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
69393ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
69409371c9d4SSatish Balay       }
69419371c9d4SSatish Balay       break;
6942552f7358SJed Brown     case INSERT_ALL_VALUES:
694397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
694497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
694597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
694697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
69479566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
69483ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
69499371c9d4SSatish Balay       }
69509371c9d4SSatish Balay       break;
6951a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
695297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
695397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
695497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
695597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
69569566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
69573ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
69589371c9d4SSatish Balay       }
69599371c9d4SSatish Balay       break;
6960552f7358SJed Brown     case ADD_VALUES:
696197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
696297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
696397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
696497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
69659566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
69663ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
69679371c9d4SSatish Balay       }
69689371c9d4SSatish Balay       break;
6969552f7358SJed Brown     case ADD_ALL_VALUES:
697097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
697197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
697297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
697397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
69749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
69753ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
69769371c9d4SSatish Balay       }
69779371c9d4SSatish Balay       break;
6978304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
697997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
698097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
698197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
698297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
69839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
69843ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
69859371c9d4SSatish Balay       }
69869371c9d4SSatish Balay       break;
6987d71ae5a4SJacob Faibussowitsch     default:
6988d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6989552f7358SJed Brown     }
69909566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
6991552f7358SJed Brown   }
69921a271a75SMatthew G. Knepley   /* Cleanup points */
69939566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
69941a271a75SMatthew G. Knepley   /* Cleanup array */
69959566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6997552f7358SJed Brown }
6998552f7358SJed Brown 
69995f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
7000d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
7001d71ae5a4SJacob Faibussowitsch {
70025f790a90SMatthew G. Knepley   PetscFunctionBegin;
700311cc89d2SBarry Smith   *contains = PETSC_TRUE;
70045f790a90SMatthew G. Knepley   if (label) {
7005d6177c40SToby Isaac     PetscInt fdof;
70065f790a90SMatthew G. Knepley 
700711cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
700811cc89d2SBarry Smith     if (!*contains) {
70099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70105f790a90SMatthew G. Knepley       *offset += fdof;
70113ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
70125f790a90SMatthew G. Knepley     }
70135f790a90SMatthew G. Knepley   }
70143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70155f790a90SMatthew G. Knepley }
70165f790a90SMatthew G. Knepley 
701797529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
7018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode)
7019d71ae5a4SJacob Faibussowitsch {
7020e07394fbSMatthew G. Knepley   PetscSection    clSection;
7021e07394fbSMatthew G. Knepley   IS              clPoints;
7022e07394fbSMatthew G. Knepley   PetscScalar    *array;
7023e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
702497529cf3SJed Brown   const PetscInt *clp;
7025e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
702697e99dd9SToby Isaac   PetscInt        offset = 0, f;
7027e07394fbSMatthew G. Knepley 
7028e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
7029e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70309566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
7031e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7032e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
70339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7034e07394fbSMatthew G. Knepley   /* Get points */
703507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
7036e07394fbSMatthew G. Knepley   /* Get array */
70379566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
7038e07394fbSMatthew G. Knepley   /* Get values */
7039e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
704097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
704197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
704211cc89d2SBarry Smith     PetscBool           contains;
704397e99dd9SToby Isaac 
7044e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
7045e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
7046e07394fbSMatthew G. Knepley         PetscInt fdof;
70479566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
7048e07394fbSMatthew G. Knepley         offset += fdof;
7049e07394fbSMatthew G. Knepley       }
7050e07394fbSMatthew G. Knepley       continue;
7051e07394fbSMatthew G. Knepley     }
70529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7053e07394fbSMatthew G. Knepley     switch (mode) {
7054e07394fbSMatthew G. Knepley     case INSERT_VALUES:
705597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
705697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
705797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
705897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
705911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
706011cc89d2SBarry Smith         if (!contains) continue;
70619566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
70629371c9d4SSatish Balay       }
70639371c9d4SSatish Balay       break;
7064e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
706597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
706697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
706797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
706897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
706911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
707011cc89d2SBarry Smith         if (!contains) continue;
70719566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
70729371c9d4SSatish Balay       }
70739371c9d4SSatish Balay       break;
7074e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
707597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
707697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
707797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
707897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
707911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
708011cc89d2SBarry Smith         if (!contains) continue;
70819566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
70829371c9d4SSatish Balay       }
70839371c9d4SSatish Balay       break;
7084e07394fbSMatthew G. Knepley     case ADD_VALUES:
708597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
708697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
708797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
708897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
708911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
709011cc89d2SBarry Smith         if (!contains) continue;
70919566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
70929371c9d4SSatish Balay       }
70939371c9d4SSatish Balay       break;
7094e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
709597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
709697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
709797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
709897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
709911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
710011cc89d2SBarry Smith         if (!contains) continue;
71019566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
71029371c9d4SSatish Balay       }
71039371c9d4SSatish Balay       break;
7104d71ae5a4SJacob Faibussowitsch     default:
7105d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7106e07394fbSMatthew G. Knepley     }
71079566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7108e07394fbSMatthew G. Knepley   }
7109e07394fbSMatthew G. Knepley   /* Cleanup points */
71109566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
7111e07394fbSMatthew G. Knepley   /* Cleanup array */
71129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
71133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7114e07394fbSMatthew G. Knepley }
7115e07394fbSMatthew G. Knepley 
7116d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
7117d71ae5a4SJacob Faibussowitsch {
7118552f7358SJed Brown   PetscMPIInt rank;
7119552f7358SJed Brown   PetscInt    i, j;
7120552f7358SJed Brown 
7121552f7358SJed Brown   PetscFunctionBegin;
71229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
712363a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
712463a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
712563a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
7126b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
71273ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
7128b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
71299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
7130b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
7131519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
71329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
7133552f7358SJed Brown #else
71349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
7135552f7358SJed Brown #endif
7136552f7358SJed Brown     }
71379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
7138552f7358SJed Brown   }
71393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7140552f7358SJed Brown }
7141552f7358SJed Brown 
714205586334SMatthew G. Knepley /*
714305586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
714405586334SMatthew G. Knepley 
714505586334SMatthew G. Knepley   Input Parameters:
714605586334SMatthew G. Knepley + section - The section for this data layout
714736fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
714805586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
714905586334SMatthew G. Knepley . off     - The global offset of this point
715005586334SMatthew G. Knepley . loff    - The local offset of each field
7151a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
715205586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
715305586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
715405586334SMatthew G. Knepley 
715505586334SMatthew G. Knepley   Output Parameter:
715605586334SMatthew G. Knepley . indices - Indices for dofs on this point
715705586334SMatthew G. Knepley 
715805586334SMatthew G. Knepley   Level: developer
715905586334SMatthew G. Knepley 
716005586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
716105586334SMatthew G. Knepley */
7162d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
7163d71ae5a4SJacob Faibussowitsch {
7164e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
7165552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7166552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7167552f7358SJed Brown   PetscInt        cind = 0, k;
7168552f7358SJed Brown 
7169552f7358SJed Brown   PetscFunctionBegin;
717008401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
71719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
71729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
7173552f7358SJed Brown   if (!cdof || setBC) {
717405586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
717505586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
717605586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
717705586334SMatthew G. Knepley 
717805586334SMatthew G. Knepley       indices[ind] = off + k;
7179552f7358SJed Brown     }
7180552f7358SJed Brown   } else {
71819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
71824acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
718305586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
718405586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
718505586334SMatthew G. Knepley 
71864acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
71874acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
718805586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
71894acb8e1eSToby Isaac         ++cind;
71904acb8e1eSToby Isaac       } else {
719136fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7192552f7358SJed Brown       }
7193552f7358SJed Brown     }
7194552f7358SJed Brown   }
7195e6ccafaeSMatthew G Knepley   *loff += dof;
71963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7197552f7358SJed Brown }
7198552f7358SJed Brown 
71997e29afd2SMatthew G. Knepley /*
720036fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
72017e29afd2SMatthew G. Knepley 
720236fa2b79SJed Brown  Input Parameters:
720336fa2b79SJed Brown + section - a section (global or local)
720420f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
720536fa2b79SJed Brown . point - point within section
720636fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
720736fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
720836fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
720936fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
721036fa2b79SJed Brown . permsoff - offset
721136fa2b79SJed Brown - indperm - index permutation
721236fa2b79SJed Brown 
721336fa2b79SJed Brown  Output Parameter:
721436fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
721536fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
721636fa2b79SJed Brown 
721736fa2b79SJed Brown  Notes:
721836fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
721936fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
722036fa2b79SJed Brown  in the local vector.
722136fa2b79SJed Brown 
722236fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
722336fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
722436fa2b79SJed Brown 
722536fa2b79SJed Brown  Developer Note:
722636fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
722736fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
722836fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
722936fa2b79SJed Brown 
723036fa2b79SJed Brown  Example:
723136fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
723236fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
723336fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
723436fa2b79SJed 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.
723536fa2b79SJed Brown 
723636fa2b79SJed Brown  Level: developer
72377e29afd2SMatthew G. Knepley */
7238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7239d71ae5a4SJacob Faibussowitsch {
7240552f7358SJed Brown   PetscInt numFields, foff, f;
7241552f7358SJed Brown 
7242552f7358SJed Brown   PetscFunctionBegin;
724308401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
72449566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7245552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
72464acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7247552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
72484acb8e1eSToby Isaac     PetscInt        cind = 0, b;
72494acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7250552f7358SJed Brown 
72519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
72529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7253552f7358SJed Brown     if (!cfdof || setBC) {
725405586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
725505586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
725605586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
725705586334SMatthew G. Knepley 
725805586334SMatthew G. Knepley         indices[ind] = off + foff + b;
725905586334SMatthew G. Knepley       }
7260552f7358SJed Brown     } else {
72619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
726205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
726305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
726405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
726505586334SMatthew G. Knepley 
72664acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
726705586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7268552f7358SJed Brown           ++cind;
7269552f7358SJed Brown         } else {
727036fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7271552f7358SJed Brown         }
7272552f7358SJed Brown       }
7273552f7358SJed Brown     }
727436fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7275552f7358SJed Brown     foffs[f] += fdof;
7276552f7358SJed Brown   }
72773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7278552f7358SJed Brown }
7279552f7358SJed Brown 
72807e29afd2SMatthew G. Knepley /*
72817e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
72827e29afd2SMatthew G. Knepley 
72837e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7284645102dcSJed Brown 
7285645102dcSJed Brown  Notes:
7286645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7287645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
72887e29afd2SMatthew G. Knepley */
7289d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7290d71ae5a4SJacob Faibussowitsch {
72917e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
72927e29afd2SMatthew G. Knepley 
72937e29afd2SMatthew G. Knepley   PetscFunctionBegin;
72949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
72957e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
72967e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
72977e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
72987e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
72997e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
73007e29afd2SMatthew G. Knepley 
73019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
73029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
73039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7304645102dcSJed Brown     if (!cfdof) {
730505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
730605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
730705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
730805586334SMatthew G. Knepley 
730905586334SMatthew G. Knepley         indices[ind] = foff + b;
731005586334SMatthew G. Knepley       }
73117e29afd2SMatthew G. Knepley     } else {
73129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
731305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
731405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
731505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
731605586334SMatthew G. Knepley 
73177e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
731805586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
73197e29afd2SMatthew G. Knepley           ++cind;
73207e29afd2SMatthew G. Knepley         } else {
732105586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
73227e29afd2SMatthew G. Knepley         }
73237e29afd2SMatthew G. Knepley       }
73247e29afd2SMatthew G. Knepley     }
73257e29afd2SMatthew G. Knepley     foffs[f] += fdof;
73267e29afd2SMatthew G. Knepley   }
73273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73287e29afd2SMatthew G. Knepley }
73297e29afd2SMatthew G. Knepley 
7330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft)
7331d71ae5a4SJacob Faibussowitsch {
7332d3d1a6afSToby Isaac   Mat             cMat;
7333d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7334d3d1a6afSToby Isaac   IS              aIS;
7335d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7336d3d1a6afSToby Isaac   const PetscInt *anchors;
7337e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7338d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7339d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7340d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7341d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7342d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7343d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7344d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
73456ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7346d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7347d3d1a6afSToby Isaac 
7348d3d1a6afSToby Isaac   PetscFunctionBegin;
7349d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7350d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
73519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7352d3d1a6afSToby Isaac 
73539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7354d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7355d3d1a6afSToby Isaac   if (aSec) {
73569566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
73579566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
73589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7359d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7360d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7361d3d1a6afSToby Isaac      * into the global matrix anyway) */
7362d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7363d3d1a6afSToby Isaac       PetscInt b    = points[p];
73644b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7365d3d1a6afSToby Isaac 
73669566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7367ad540459SPierre Jolivet       if (!bSecDof) continue;
736848a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7369d3d1a6afSToby Isaac       if (bDof) {
7370d3d1a6afSToby Isaac         /* this point is constrained */
7371d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7372d3d1a6afSToby Isaac         PetscInt bOff, q;
7373d3d1a6afSToby Isaac 
7374d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7375d3d1a6afSToby Isaac         newNumPoints += bDof;
73769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7377d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7378d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7379d3d1a6afSToby Isaac           PetscInt aDof;
7380d3d1a6afSToby Isaac 
73819566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7382d3d1a6afSToby Isaac           newNumIndices += aDof;
7383d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7384d3d1a6afSToby Isaac             PetscInt fDof;
7385d3d1a6afSToby Isaac 
73869566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7387d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7388d3d1a6afSToby Isaac           }
7389d3d1a6afSToby Isaac         }
73909371c9d4SSatish Balay       } else {
7391d3d1a6afSToby Isaac         /* this point is not constrained */
7392d3d1a6afSToby Isaac         newNumPoints++;
73934b2f2278SToby Isaac         newNumIndices += bSecDof;
7394d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7395d3d1a6afSToby Isaac           PetscInt fDof;
7396d3d1a6afSToby Isaac 
73979566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7398d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7399d3d1a6afSToby Isaac         }
7400d3d1a6afSToby Isaac       }
7401d3d1a6afSToby Isaac     }
7402d3d1a6afSToby Isaac   }
7403d3d1a6afSToby Isaac   if (!anyConstrained) {
740472b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
740572b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
740672b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
740772b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
74089566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
74093ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7410d3d1a6afSToby Isaac   }
7411d3d1a6afSToby Isaac 
74126ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
74136ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
74146ecaa68aSToby Isaac 
7415f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7416d3d1a6afSToby Isaac 
74176ecaa68aSToby Isaac   if (!outPoints && !outValues) {
74186ecaa68aSToby Isaac     if (offsets) {
7419ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
74206ecaa68aSToby Isaac     }
74219566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
74223ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
74236ecaa68aSToby Isaac   }
74246ecaa68aSToby Isaac 
74251dca8a05SBarry Smith   PetscCheck(!numFields || newOffsets[numFields] == newNumIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, newOffsets[numFields], newNumIndices);
7426d3d1a6afSToby Isaac 
74279566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7428d3d1a6afSToby Isaac 
7429d3d1a6afSToby Isaac   /* workspaces */
7430d3d1a6afSToby Isaac   if (numFields) {
7431d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
74329566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
74339566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7434d3d1a6afSToby Isaac     }
74359371c9d4SSatish Balay   } else {
74369566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
74379566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7438d3d1a6afSToby Isaac   }
7439d3d1a6afSToby Isaac 
7440d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7441d3d1a6afSToby Isaac   if (numFields) {
74424b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
74434b2f2278SToby Isaac 
7444d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7445d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
74464b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7447d3d1a6afSToby Isaac 
74489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
74494b2f2278SToby Isaac       if (!bSecDof) {
74504b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
74514b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
74524b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
74534b2f2278SToby Isaac         }
74544b2f2278SToby Isaac         continue;
74554b2f2278SToby Isaac       }
745648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7457d3d1a6afSToby Isaac       if (bDof) {
7458d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7459d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7460d3d1a6afSToby Isaac 
74619566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
74629566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7463d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7464d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7465d3d1a6afSToby Isaac             PetscInt aFDof;
7466d3d1a6afSToby Isaac 
74679566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7468d3d1a6afSToby Isaac             allFDof += aFDof;
7469d3d1a6afSToby Isaac           }
7470d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7471d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7472d3d1a6afSToby Isaac         }
74739371c9d4SSatish Balay       } else {
7474d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7475d3d1a6afSToby Isaac           PetscInt fDof;
7476d3d1a6afSToby Isaac 
74779566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7478d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7479d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7480d3d1a6afSToby Isaac         }
7481d3d1a6afSToby Isaac       }
7482d3d1a6afSToby Isaac     }
74834b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
74844b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
74854b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7486d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7487d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7488d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7489d3d1a6afSToby Isaac       }
749019f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
749119f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
74929566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7493d3d1a6afSToby Isaac     }
74949371c9d4SSatish Balay   } else {
7495d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7496d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
74974b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7498d3d1a6afSToby Isaac 
74999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
75004b2f2278SToby Isaac       if (!bSecDof) {
75014b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
75024b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
75034b2f2278SToby Isaac         continue;
75044b2f2278SToby Isaac       }
750548a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7506d3d1a6afSToby Isaac       if (bDof) {
75074b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7508d3d1a6afSToby Isaac 
75099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7510d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7511d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7512d3d1a6afSToby Isaac 
75139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7514d3d1a6afSToby Isaac           allDof += aDof;
7515d3d1a6afSToby Isaac         }
7516d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
75174b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
75189371c9d4SSatish Balay       } else {
75194b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7520d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7521d3d1a6afSToby Isaac       }
7522d3d1a6afSToby Isaac     }
7523d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7524d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7525d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7526d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7527d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7528d3d1a6afSToby Isaac     }
75299566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7530d3d1a6afSToby Isaac   }
7531d3d1a6afSToby Isaac 
75326ecaa68aSToby Isaac   /* output arrays */
75339566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
75346ecaa68aSToby Isaac 
7535d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
75369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
75379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
75389566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
75399566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7540d3d1a6afSToby Isaac   if (numFields) {
7541d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7542d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7543d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
75444b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7545d3d1a6afSToby Isaac 
75469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7547ad540459SPierre Jolivet       if (!bSecDof) continue;
754848a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7549d3d1a6afSToby Isaac       if (bDof) {
7550d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7551d3d1a6afSToby Isaac 
7552d3d1a6afSToby Isaac         fStart[0] = 0;
7553d3d1a6afSToby Isaac         fEnd[0]   = 0;
7554d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7555d3d1a6afSToby Isaac           PetscInt fDof;
7556d3d1a6afSToby Isaac 
75579566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7558d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7559d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7560d3d1a6afSToby Isaac         }
75619566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
75629566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7563d3d1a6afSToby Isaac 
7564d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7565d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7566d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7567d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7568d3d1a6afSToby Isaac 
7569d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7570d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7571d3d1a6afSToby Isaac         }
75729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7573d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7574d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7575d3d1a6afSToby Isaac 
7576d3d1a6afSToby 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 */
7577d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7578d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
75799566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
75809566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7581d3d1a6afSToby Isaac         }
7582d3d1a6afSToby Isaac         newP += bDof;
7583d3d1a6afSToby Isaac 
75846ecaa68aSToby Isaac         if (outValues) {
7585d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
758648a46eb9SPierre Jolivet           for (f = 0; f < numFields; f++) PetscCall(MatGetValues(cMat, fEnd[f] - fStart[f], indices + fStart[f], fAnchorEnd[f] - fAnchorStart[f], newIndices + fAnchorStart[f], pointMat[f] + pointMatOffsets[f][p]));
7587d3d1a6afSToby Isaac         }
75889371c9d4SSatish Balay       } else {
7589d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7590d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7591d3d1a6afSToby Isaac         newP++;
7592d3d1a6afSToby Isaac       }
7593d3d1a6afSToby Isaac     }
7594d3d1a6afSToby Isaac   } else {
7595d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7596d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7597d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
75984b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7599d3d1a6afSToby Isaac 
76009566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7601ad540459SPierre Jolivet       if (!bSecDof) continue;
760248a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7603d3d1a6afSToby Isaac       if (bDof) {
7604d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7605d3d1a6afSToby Isaac 
76069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
76079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7608d3d1a6afSToby Isaac 
76099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7610d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7611d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7612d3d1a6afSToby Isaac 
7613d3d1a6afSToby 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 */
7614d3d1a6afSToby Isaac 
7615d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7616d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
76179566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
76189566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7619d3d1a6afSToby Isaac         }
7620d3d1a6afSToby Isaac         newP += bDof;
7621d3d1a6afSToby Isaac 
7622d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
762348a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
76249371c9d4SSatish Balay       } else {
7625d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7626d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7627d3d1a6afSToby Isaac         newP++;
7628d3d1a6afSToby Isaac       }
7629d3d1a6afSToby Isaac     }
7630d3d1a6afSToby Isaac   }
7631d3d1a6afSToby Isaac 
76326ecaa68aSToby Isaac   if (outValues) {
76339566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
76349566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7635d3d1a6afSToby Isaac     /* multiply constraints on the right */
7636d3d1a6afSToby Isaac     if (numFields) {
7637d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7638d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7639d3d1a6afSToby Isaac 
7640d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7641d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7642d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7643d3d1a6afSToby Isaac           PetscInt c, r, k;
7644d3d1a6afSToby Isaac           PetscInt dof;
7645d3d1a6afSToby Isaac 
76469566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7647ad540459SPierre Jolivet           if (!dof) continue;
7648d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7649d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7650d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7651d3d1a6afSToby Isaac 
7652d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7653d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7654ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7655d3d1a6afSToby Isaac               }
7656d3d1a6afSToby Isaac             }
76579371c9d4SSatish Balay           } else {
7658d3d1a6afSToby Isaac             /* copy this column as is */
7659d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7660ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7661d3d1a6afSToby Isaac             }
7662d3d1a6afSToby Isaac           }
7663d3d1a6afSToby Isaac           oldOff += dof;
7664d3d1a6afSToby Isaac         }
7665d3d1a6afSToby Isaac       }
76669371c9d4SSatish Balay     } else {
7667d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7668d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7669d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7670d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7671d3d1a6afSToby Isaac         PetscInt c, r, k;
7672d3d1a6afSToby Isaac         PetscInt dof;
7673d3d1a6afSToby Isaac 
76749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7675ad540459SPierre Jolivet         if (!dof) continue;
7676d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7677d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7678d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7679d3d1a6afSToby Isaac 
7680d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7681d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7682ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7683d3d1a6afSToby Isaac             }
7684d3d1a6afSToby Isaac           }
76859371c9d4SSatish Balay         } else {
7686d3d1a6afSToby Isaac           /* copy this column as is */
7687d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7688ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7689d3d1a6afSToby Isaac           }
7690d3d1a6afSToby Isaac         }
7691d3d1a6afSToby Isaac         oldOff += dof;
7692d3d1a6afSToby Isaac       }
7693d3d1a6afSToby Isaac     }
7694d3d1a6afSToby Isaac 
76956ecaa68aSToby Isaac     if (multiplyLeft) {
76969566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
76979566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7698d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7699d3d1a6afSToby Isaac       if (numFields) {
7700d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7701d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7702d3d1a6afSToby Isaac 
7703d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7704d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7705d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7706d3d1a6afSToby Isaac             PetscInt c, r, k;
7707d3d1a6afSToby Isaac             PetscInt dof;
7708d3d1a6afSToby Isaac 
77099566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7710d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7711d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7712d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7713d3d1a6afSToby Isaac 
7714d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7715d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7716ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7717d3d1a6afSToby Isaac                 }
7718d3d1a6afSToby Isaac               }
77199371c9d4SSatish Balay             } else {
7720d3d1a6afSToby Isaac               /* copy this row as is */
7721d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7722ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7723d3d1a6afSToby Isaac               }
7724d3d1a6afSToby Isaac             }
7725d3d1a6afSToby Isaac             oldOff += dof;
7726d3d1a6afSToby Isaac           }
7727d3d1a6afSToby Isaac         }
77289371c9d4SSatish Balay       } else {
7729d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7730d3d1a6afSToby Isaac 
7731d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7732d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7733d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7734d3d1a6afSToby Isaac           PetscInt c, r, k;
7735d3d1a6afSToby Isaac           PetscInt dof;
7736d3d1a6afSToby Isaac 
77379566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7738d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7739d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7740d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7741d3d1a6afSToby Isaac 
7742d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7743d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7744ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7745d3d1a6afSToby Isaac               }
7746d3d1a6afSToby Isaac             }
77479371c9d4SSatish Balay           } else {
7748d3d1a6afSToby Isaac             /* copy this row as is */
77499fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7750ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7751d3d1a6afSToby Isaac             }
7752d3d1a6afSToby Isaac           }
7753d3d1a6afSToby Isaac           oldOff += dof;
7754d3d1a6afSToby Isaac         }
7755d3d1a6afSToby Isaac       }
7756d3d1a6afSToby Isaac 
77579566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
77589371c9d4SSatish Balay     } else {
77596ecaa68aSToby Isaac       newValues = tmpValues;
77606ecaa68aSToby Isaac     }
77616ecaa68aSToby Isaac   }
77626ecaa68aSToby Isaac 
7763d3d1a6afSToby Isaac   /* clean up */
77649566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
77659566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
77666ecaa68aSToby Isaac 
7767d3d1a6afSToby Isaac   if (numFields) {
7768d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
77699566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
77709566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
77719566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7772d3d1a6afSToby Isaac     }
77739371c9d4SSatish Balay   } else {
77749566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
77759566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
77769566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7777d3d1a6afSToby Isaac   }
77789566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7779d3d1a6afSToby Isaac 
7780d3d1a6afSToby Isaac   /* output */
77816ecaa68aSToby Isaac   if (outPoints) {
7782d3d1a6afSToby Isaac     *outPoints = newPoints;
77839371c9d4SSatish Balay   } else {
77849566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
77856ecaa68aSToby Isaac   }
7786ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7787ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
77883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7789d3d1a6afSToby Isaac }
7790d3d1a6afSToby Isaac 
77914a1e0b3eSMatthew G. Knepley /*@C
779271f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
77937cd05799SMatthew G. Knepley 
77947cd05799SMatthew G. Knepley   Not collective
77957cd05799SMatthew G. Knepley 
77967cd05799SMatthew G. Knepley   Input Parameters:
7797a1cb98faSBarry Smith + dm         - The `DM`
7798a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7799a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
780071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
780171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
78027cd05799SMatthew G. Knepley 
780371f0bbf9SMatthew G. Knepley   Output Parameters:
780471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
780571f0bbf9SMatthew G. Knepley . indices    - The dof indices
780620f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
780720f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
78087cd05799SMatthew G. Knepley 
7809a1cb98faSBarry Smith   Level: advanced
781036fa2b79SJed Brown 
7811a1cb98faSBarry Smith   Notes:
7812a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7813a1cb98faSBarry Smith 
781420f4b53cSBarry Smith   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
781520f4b53cSBarry Smith   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
781636fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
781720f4b53cSBarry Smith   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
781836fa2b79SJed Brown   indices (with the above semantics) are implied.
78197cd05799SMatthew G. Knepley 
78201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7821a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
78224a1e0b3eSMatthew G. Knepley @*/
7823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7824d71ae5a4SJacob Faibussowitsch {
782571f0bbf9SMatthew G. Knepley   /* Closure ordering */
78267773e69fSMatthew G. Knepley   PetscSection    clSection;
78277773e69fSMatthew G. Knepley   IS              clPoints;
782871f0bbf9SMatthew G. Knepley   const PetscInt *clp;
782971f0bbf9SMatthew G. Knepley   PetscInt       *points;
783071f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
783171f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
78324acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
783371f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
783471f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
783571f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
783671f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
783771f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
783871f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
783971f0bbf9SMatthew G. Knepley 
784071f0bbf9SMatthew G. Knepley   PetscInt *idx;
784171f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
784271f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
78437773e69fSMatthew G. Knepley 
784471f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
78457773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78467773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
784736fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
78484f572ea9SToby Isaac   if (numIndices) PetscAssertPointer(numIndices, 6);
78494f572ea9SToby Isaac   if (indices) PetscAssertPointer(indices, 7);
78504f572ea9SToby Isaac   if (outOffsets) PetscAssertPointer(outOffsets, 8);
78514f572ea9SToby Isaac   if (values) PetscAssertPointer(values, 9);
78529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
785363a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
78549566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
785571f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
785607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7857c459fbc1SJed Brown   if (useClPerm) {
7858c459fbc1SJed Brown     PetscInt depth, clsize;
78599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7860c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7861c459fbc1SJed Brown       PetscInt dof;
78629566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7863c459fbc1SJed Brown       clsize += dof;
7864c459fbc1SJed Brown     }
78659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7866c459fbc1SJed Brown   }
786771f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
786871f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
78697773e69fSMatthew G. Knepley     PetscInt dof, fdof;
78707773e69fSMatthew G. Knepley 
78719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
78727773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
78739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
78747773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
78757773e69fSMatthew G. Knepley     }
787671f0bbf9SMatthew G. Knepley     Ni += dof;
78777773e69fSMatthew G. Knepley   }
78787773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
78791dca8a05SBarry Smith   PetscCheck(!Nf || offsets[Nf] == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[Nf], Ni);
788071f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
788171f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
78829566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
78839566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
788471f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
788571f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
788671f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
78876ecaa68aSToby Isaac 
788871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
788971f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
789071f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
789171f0bbf9SMatthew G. Knepley 
78929566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
78939566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
789471f0bbf9SMatthew G. Knepley         if (flip) {
789571f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
789671f0bbf9SMatthew G. Knepley 
789771f0bbf9SMatthew G. Knepley           if (!valCopy) {
78989566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
789971f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
790071f0bbf9SMatthew G. Knepley             *values = valCopy;
790171f0bbf9SMatthew G. Knepley           }
790271f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
790371f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
790471f0bbf9SMatthew G. Knepley 
790571f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
790671f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
790771f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
79086ecaa68aSToby Isaac             }
79096ecaa68aSToby Isaac           }
791071f0bbf9SMatthew G. Knepley         }
791171f0bbf9SMatthew G. Knepley         foffset += fdof;
791271f0bbf9SMatthew G. Knepley       }
791371f0bbf9SMatthew G. Knepley     }
791471f0bbf9SMatthew G. Knepley   }
791571f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
79169566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
791771f0bbf9SMatthew G. Knepley   if (NclC) {
79189566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
791971f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
79209566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
79219566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
792271f0bbf9SMatthew G. Knepley     }
792371f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
79249566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
79259566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
792671f0bbf9SMatthew G. Knepley     }
79279566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
792871f0bbf9SMatthew G. Knepley     Ncl    = NclC;
792971f0bbf9SMatthew G. Knepley     Ni     = NiC;
793071f0bbf9SMatthew G. Knepley     points = pointsC;
793171f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
793271f0bbf9SMatthew G. Knepley   }
793371f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
79349566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
793571f0bbf9SMatthew G. Knepley   if (Nf) {
793671f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
793771f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
793871f0bbf9SMatthew G. Knepley 
79399371c9d4SSatish Balay     if (outOffsets) {
79409371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
79419371c9d4SSatish Balay     }
79429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
794371f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
794471f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
794571f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
794671f0bbf9SMatthew G. Knepley 
79479566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
79487773e69fSMatthew G. Knepley       }
79497773e69fSMatthew G. Knepley     } else {
795071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
795171f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
795271f0bbf9SMatthew G. Knepley 
79539566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
795471f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
795571f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
795671f0bbf9SMatthew G. Knepley          * global section. */
79579566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
795871f0bbf9SMatthew G. Knepley       }
795971f0bbf9SMatthew G. Knepley     }
796071f0bbf9SMatthew G. Knepley   } else {
796171f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
796271f0bbf9SMatthew G. Knepley 
796371f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
796471f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
79654acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
79664acb8e1eSToby Isaac 
79679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
796871f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
796971f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
79709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
79717773e69fSMatthew G. Knepley     }
79727773e69fSMatthew G. Knepley   }
797371f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
797471f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
79759566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
79769566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
79774acb8e1eSToby Isaac   }
797871f0bbf9SMatthew G. Knepley   if (NclC) {
79799566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
79807773e69fSMatthew G. Knepley   } else {
79819566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
79827773e69fSMatthew G. Knepley   }
798371f0bbf9SMatthew G. Knepley 
798471f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
798571f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
79863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79877773e69fSMatthew G. Knepley }
79887773e69fSMatthew G. Knepley 
79897cd05799SMatthew G. Knepley /*@C
799071f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
79917cd05799SMatthew G. Knepley 
79927cd05799SMatthew G. Knepley   Not collective
79937cd05799SMatthew G. Knepley 
79947cd05799SMatthew G. Knepley   Input Parameters:
7995a1cb98faSBarry Smith + dm         - The `DM`
7996a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7997a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
799871f0bbf9SMatthew G. Knepley . point      - The point defining the closure
799971f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
800071f0bbf9SMatthew G. Knepley 
800171f0bbf9SMatthew G. Knepley   Output Parameters:
800271f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
800371f0bbf9SMatthew G. Knepley . indices    - The dof indices
800420f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
800520f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
800671f0bbf9SMatthew G. Knepley 
8007a1cb98faSBarry Smith   Level: advanced
800871f0bbf9SMatthew G. Knepley 
8009a1cb98faSBarry Smith   Notes:
8010a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
8011a1cb98faSBarry Smith 
8012a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
801371f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
801471f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
801571f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
801671f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
80177cd05799SMatthew G. Knepley 
80181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
80197cd05799SMatthew G. Knepley @*/
8020d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8021d71ae5a4SJacob Faibussowitsch {
80227773e69fSMatthew G. Knepley   PetscFunctionBegin;
80237773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80244f572ea9SToby Isaac   PetscAssertPointer(indices, 7);
80259566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
80263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80277773e69fSMatthew G. Knepley }
80287773e69fSMatthew G. Knepley 
8029e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8030d71ae5a4SJacob Faibussowitsch {
8031552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
8032552f7358SJed Brown   PetscInt          *indices;
803371f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
803471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
8035552f7358SJed Brown   PetscErrorCode     ierr;
8036552f7358SJed Brown 
8037552f7358SJed Brown   PetscFunctionBegin;
8038552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80399566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
80403dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
80419566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
80423dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
8043e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 5);
8044552f7358SJed Brown 
8045e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values));
80460d644c17SKarl Rupp 
80479566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
8048d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
80494a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
8050552f7358SJed Brown   if (ierr) {
8051552f7358SJed Brown     PetscMPIInt rank;
8052552f7358SJed Brown 
80539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
80549566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
80559566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
80569566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
80579566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
8058c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
8059552f7358SJed Brown   }
80604a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
80614a1e0b3eSMatthew G. Knepley     PetscInt i;
80629566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
806363a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
80649566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
80654a1e0b3eSMatthew G. Knepley   }
806671f0bbf9SMatthew G. Knepley 
80679566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
80689566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
80693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80704acb8e1eSToby Isaac }
807171f0bbf9SMatthew G. Knepley 
80724a1e0b3eSMatthew G. Knepley /*@C
8073e8e188d2SZach Atkins   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
8074e8e188d2SZach Atkins 
8075e8e188d2SZach Atkins   Not collective
8076e8e188d2SZach Atkins 
8077e8e188d2SZach Atkins   Input Parameters:
8078e8e188d2SZach Atkins + dm            - The `DM`
8079e8e188d2SZach Atkins . section       - The section describing the layout in `v`, or `NULL` to use the default section
8080e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
8081e8e188d2SZach Atkins . A             - The matrix
8082e8e188d2SZach Atkins . point         - The point in the `DM`
8083e8e188d2SZach Atkins . values        - The array of values
8084e8e188d2SZach Atkins - mode          - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
8085e8e188d2SZach Atkins 
8086e8e188d2SZach Atkins   Level: intermediate
8087e8e188d2SZach Atkins 
8088e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
8089e8e188d2SZach Atkins @*/
8090e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8091e8e188d2SZach Atkins {
8092e8e188d2SZach Atkins   PetscFunctionBegin;
8093e8e188d2SZach Atkins   PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode));
8094e8e188d2SZach Atkins   PetscFunctionReturn(PETSC_SUCCESS);
8095e8e188d2SZach Atkins }
8096e8e188d2SZach Atkins 
8097e8e188d2SZach Atkins /*@C
809860225df5SJacob Faibussowitsch   DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section
80994a1e0b3eSMatthew G. Knepley 
81004a1e0b3eSMatthew G. Knepley   Not collective
81014a1e0b3eSMatthew G. Knepley 
81024a1e0b3eSMatthew G. Knepley   Input Parameters:
8103a1cb98faSBarry Smith + dmRow            - The `DM` for the row fields
810420f4b53cSBarry Smith . sectionRow       - The section describing the layout, or `NULL` to use the default section in `dmRow`
8105e8e188d2SZach Atkins . useRowPerm       - The flag to use the closure permutation of the `dmRow` if available
810620f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
8107a1cb98faSBarry Smith . dmCol            - The `DM` for the column fields
810820f4b53cSBarry Smith . sectionCol       - The section describing the layout, or `NULL` to use the default section in `dmCol`
8109e8e188d2SZach Atkins . useColPerm       - The flag to use the closure permutation of the `dmCol` if available
811020f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
81114a1e0b3eSMatthew G. Knepley . A                - The matrix
8112a1cb98faSBarry Smith . point            - The point in the `DM`
81134a1e0b3eSMatthew G. Knepley . values           - The array of values
8114a1cb98faSBarry Smith - mode             - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
81154a1e0b3eSMatthew G. Knepley 
81164a1e0b3eSMatthew G. Knepley   Level: intermediate
81174a1e0b3eSMatthew G. Knepley 
81181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
81194a1e0b3eSMatthew G. Knepley @*/
8120e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, PetscBool useRowPerm, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, PetscBool useColPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8121d71ae5a4SJacob Faibussowitsch {
812271f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
812371f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
812471f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
812571f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
812671f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
812771f0bbf9SMatthew G. Knepley 
812871f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
812971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
81309566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
813171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
81329566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
813371f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
8134e8e188d2SZach Atkins   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5);
81359566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
8136e8e188d2SZach Atkins   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6);
81379566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
8138e8e188d2SZach Atkins   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7);
8139e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 9);
814071f0bbf9SMatthew G. Knepley 
8141e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
8142e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
814371f0bbf9SMatthew G. Knepley 
81449566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
8145d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
81464a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
814771f0bbf9SMatthew G. Knepley   if (ierr) {
814871f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
814971f0bbf9SMatthew G. Knepley 
81509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81519566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81529566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
81539566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
81549566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
81559566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
8156d3d1a6afSToby Isaac   }
815771f0bbf9SMatthew G. Knepley 
8158e8e188d2SZach Atkins   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
8159e8e188d2SZach Atkins   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
81609566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
81613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8162552f7358SJed Brown }
8163552f7358SJed Brown 
8164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8165d71ae5a4SJacob Faibussowitsch {
8166de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
8167de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
8168de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
8169de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
817017c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8171de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
8172412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
81734ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
8174de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
8175de41b84cSMatthew G. Knepley 
8176de41b84cSMatthew G. Knepley   PetscFunctionBegin;
8177de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
8178de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
81799566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
8180de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
81819566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
8182de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
81839566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
8184de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
81859566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
8186de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
8187de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
81889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
818963a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
81909566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
81919566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
8192de41b84cSMatthew G. Knepley   /* Column indices */
81939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81944ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
8195de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
8196de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
81979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8198de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8199de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8200de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8201de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8202de41b84cSMatthew G. Knepley       ++q;
8203de41b84cSMatthew G. Knepley     }
8204de41b84cSMatthew G. Knepley   }
8205de41b84cSMatthew G. Knepley   numCPoints = q;
8206de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8207de41b84cSMatthew G. Knepley     PetscInt fdof;
8208de41b84cSMatthew G. Knepley 
82099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
82104ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8211de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
82129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8213de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8214de41b84cSMatthew G. Knepley     }
8215de41b84cSMatthew G. Knepley     numCIndices += dof;
8216de41b84cSMatthew G. Knepley   }
8217de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8218de41b84cSMatthew G. Knepley   /* Row indices */
82199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8220412e9a14SMatthew G. Knepley   {
8221012bc364SMatthew G. Knepley     DMPlexTransform tr;
8222012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8223012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8224012bc364SMatthew G. Knepley 
82259566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
82269566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
82279566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8228012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
82299566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8230412e9a14SMatthew G. Knepley   }
82319566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8232de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8233de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
82349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8235de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
82369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8237de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8238de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
82399566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
82404ca5e9f5SMatthew G. Knepley         if (!dof) continue;
82419371c9d4SSatish Balay         for (s = 0; s < q; ++s)
82429371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
82434ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8244de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8245de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8246de41b84cSMatthew G. Knepley         ++q;
8247de41b84cSMatthew G. Knepley       }
8248de41b84cSMatthew G. Knepley     }
82499566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8250de41b84cSMatthew G. Knepley   }
8251de41b84cSMatthew G. Knepley   numFPoints = q;
8252de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8253de41b84cSMatthew G. Knepley     PetscInt fdof;
8254de41b84cSMatthew G. Knepley 
82559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
82564ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8257de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
82589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8259de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8260de41b84cSMatthew G. Knepley     }
8261de41b84cSMatthew G. Knepley     numFIndices += dof;
8262de41b84cSMatthew G. Knepley   }
8263de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8264de41b84cSMatthew G. Knepley 
82651dca8a05SBarry Smith   PetscCheck(!numFields || foffsets[numFields] == numFIndices, PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices);
82661dca8a05SBarry Smith   PetscCheck(!numFields || coffsets[numFields] == numCIndices, PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices);
82679566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
82689566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8269de41b84cSMatthew G. Knepley   if (numFields) {
82704acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
82714acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
82724acb8e1eSToby Isaac 
82734acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8276de41b84cSMatthew G. Knepley     }
82774acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
82789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
82804acb8e1eSToby Isaac     }
82814acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
82829566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
82844acb8e1eSToby Isaac     }
82854acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82869566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82879566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8288de41b84cSMatthew G. Knepley     }
8289de41b84cSMatthew G. Knepley   } else {
82904acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
82914acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
82924acb8e1eSToby Isaac 
82939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82954acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
82964acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
82974acb8e1eSToby Isaac 
82989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82999566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8300de41b84cSMatthew G. Knepley     }
83014acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
83024acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
83034acb8e1eSToby Isaac 
83049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
83059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8306de41b84cSMatthew G. Knepley     }
83079566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
83089566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8309de41b84cSMatthew G. Knepley   }
83109566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
83114acb8e1eSToby Isaac   /* TODO: flips */
8312d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8313de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8314de41b84cSMatthew G. Knepley   if (ierr) {
8315de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8316de41b84cSMatthew G. Knepley 
83179566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
83189566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
83199566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
83209566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83219566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8322de41b84cSMatthew G. Knepley   }
83239566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
83249566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
83259566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83269566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
83273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8328de41b84cSMatthew G. Knepley }
8329de41b84cSMatthew G. Knepley 
8330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8331d71ae5a4SJacob Faibussowitsch {
83327c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
83337c927364SMatthew G. Knepley   PetscInt       *cpoints = NULL;
83347c927364SMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
833517c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8336412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
83377c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
83387c927364SMatthew G. Knepley 
83397c927364SMatthew G. Knepley   PetscFunctionBegin;
83407c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
83417c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
83429566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
83437c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
83449566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
83457c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
83469566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
83477c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
83489566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
83497c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
83509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
835163a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
83529566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
83539566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
83547c927364SMatthew G. Knepley   /* Column indices */
83559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
83567c927364SMatthew G. Knepley   maxFPoints = numCPoints;
83577c927364SMatthew G. Knepley   /* Compress out points not in the section */
83587c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
83599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
83607c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
83617c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
83627c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
83637c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
83647c927364SMatthew G. Knepley       ++q;
83657c927364SMatthew G. Knepley     }
83667c927364SMatthew G. Knepley   }
83677c927364SMatthew G. Knepley   numCPoints = q;
83687c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
83697c927364SMatthew G. Knepley     PetscInt fdof;
83707c927364SMatthew G. Knepley 
83719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
83727c927364SMatthew G. Knepley     if (!dof) continue;
83737c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
83757c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
83767c927364SMatthew G. Knepley     }
83777c927364SMatthew G. Knepley     numCIndices += dof;
83787c927364SMatthew G. Knepley   }
83797c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
83807c927364SMatthew G. Knepley   /* Row indices */
83819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8382412e9a14SMatthew G. Knepley   {
8383012bc364SMatthew G. Knepley     DMPlexTransform tr;
8384012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8385012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8386012bc364SMatthew G. Knepley 
83879566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
83889566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
83899566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8390012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
83919566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8392412e9a14SMatthew G. Knepley   }
83939566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
83947c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
83957c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
83969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
83977c927364SMatthew G. Knepley     /* Compress out points not in the section */
83989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
83997c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
84007c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
84019566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
84027c927364SMatthew G. Knepley         if (!dof) continue;
84039371c9d4SSatish Balay         for (s = 0; s < q; ++s)
84049371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
84057c927364SMatthew G. Knepley         if (s < q) continue;
84067c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
84077c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
84087c927364SMatthew G. Knepley         ++q;
84097c927364SMatthew G. Knepley       }
84107c927364SMatthew G. Knepley     }
84119566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
84127c927364SMatthew G. Knepley   }
84137c927364SMatthew G. Knepley   numFPoints = q;
84147c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
84157c927364SMatthew G. Knepley     PetscInt fdof;
84167c927364SMatthew G. Knepley 
84179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
84187c927364SMatthew G. Knepley     if (!dof) continue;
84197c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
84209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
84217c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
84227c927364SMatthew G. Knepley     }
84237c927364SMatthew G. Knepley     numFIndices += dof;
84247c927364SMatthew G. Knepley   }
84257c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
84267c927364SMatthew G. Knepley 
84271dca8a05SBarry Smith   PetscCheck(!numFields || foffsets[numFields] == numFIndices, PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices);
84281dca8a05SBarry Smith   PetscCheck(!numFields || coffsets[numFields] == numCIndices, PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices);
84297c927364SMatthew G. Knepley   if (numFields) {
84304acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
84314acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
84324acb8e1eSToby Isaac 
84334acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84349566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
84367c927364SMatthew G. Knepley     }
84374acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
84389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
84404acb8e1eSToby Isaac     }
84414acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
84429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
84444acb8e1eSToby Isaac     }
84454acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84469566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84479566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
84487c927364SMatthew G. Knepley     }
84497c927364SMatthew G. Knepley   } else {
84504acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
84514acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
84524acb8e1eSToby Isaac 
84539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
84549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
84554acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
84564acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
84574acb8e1eSToby Isaac 
84589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
84607c927364SMatthew G. Knepley     }
84614acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
84624acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
84634acb8e1eSToby Isaac 
84649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
84667c927364SMatthew G. Knepley     }
84679566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
84689566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
84697c927364SMatthew G. Knepley   }
84709566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
84719566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84737c927364SMatthew G. Knepley }
84747c927364SMatthew G. Knepley 
84757cd05799SMatthew G. Knepley /*@C
84767cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
84777cd05799SMatthew G. Knepley 
84787cd05799SMatthew G. Knepley   Input Parameter:
8479a1cb98faSBarry Smith . dm - The `DMPLEX` object
84807cd05799SMatthew G. Knepley 
84817cd05799SMatthew G. Knepley   Output Parameter:
84827cd05799SMatthew G. Knepley . cellHeight - The height of a cell
84837cd05799SMatthew G. Knepley 
84847cd05799SMatthew G. Knepley   Level: developer
84857cd05799SMatthew G. Knepley 
84861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
84877cd05799SMatthew G. Knepley @*/
8488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8489d71ae5a4SJacob Faibussowitsch {
8490552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8491552f7358SJed Brown 
8492552f7358SJed Brown   PetscFunctionBegin;
8493552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84944f572ea9SToby Isaac   PetscAssertPointer(cellHeight, 2);
8495552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
84963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8497552f7358SJed Brown }
8498552f7358SJed Brown 
84997cd05799SMatthew G. Knepley /*@C
85007cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
85017cd05799SMatthew G. Knepley 
85027cd05799SMatthew G. Knepley   Input Parameters:
8503a1cb98faSBarry Smith + dm         - The `DMPLEX` object
85047cd05799SMatthew G. Knepley - cellHeight - The height of a cell
85057cd05799SMatthew G. Knepley 
85067cd05799SMatthew G. Knepley   Level: developer
85077cd05799SMatthew G. Knepley 
85081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
85097cd05799SMatthew G. Knepley @*/
8510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8511d71ae5a4SJacob Faibussowitsch {
8512552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8513552f7358SJed Brown 
8514552f7358SJed Brown   PetscFunctionBegin;
8515552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8516552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
85173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8518552f7358SJed Brown }
8519552f7358SJed Brown 
8520e6139122SMatthew G. Knepley /*@
85212827ebadSStefano Zampini   DMPlexGetCellTypeStratum - Get the range of cells of a given celltype
8522e6139122SMatthew G. Knepley 
85232827ebadSStefano Zampini   Input Parameters:
85242827ebadSStefano Zampini + dm - The `DMPLEX` object
85252827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell
8526e6139122SMatthew G. Knepley 
8527e6139122SMatthew G. Knepley   Output Parameters:
85282827ebadSStefano Zampini + start - The first cell of this type, or `NULL`
85292827ebadSStefano Zampini - end   - The upper bound on this celltype, or `NULL`
8530e6139122SMatthew G. Knepley 
85312a9f31c0SMatthew G. Knepley   Level: advanced
8532e6139122SMatthew G. Knepley 
85332827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
8534e6139122SMatthew G. Knepley @*/
85352827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end)
8536d71ae5a4SJacob Faibussowitsch {
85372827ebadSStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
85382827ebadSStefano Zampini   DMLabel  label;
85392827ebadSStefano Zampini   PetscInt pStart, pEnd;
8540e6139122SMatthew G. Knepley 
8541e6139122SMatthew G. Knepley   PetscFunctionBegin;
8542e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85432827ebadSStefano Zampini   if (start) {
85444f572ea9SToby Isaac     PetscAssertPointer(start, 3);
85452827ebadSStefano Zampini     *start = 0;
85462827ebadSStefano Zampini   }
85472827ebadSStefano Zampini   if (end) {
85484f572ea9SToby Isaac     PetscAssertPointer(end, 4);
85492827ebadSStefano Zampini     *end = 0;
85502827ebadSStefano Zampini   }
85512827ebadSStefano Zampini   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
85522827ebadSStefano Zampini   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
85532827ebadSStefano Zampini   if (mesh->tr) {
85542827ebadSStefano Zampini     PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end));
85552827ebadSStefano Zampini   } else {
85562827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
85572827ebadSStefano Zampini     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found");
85582827ebadSStefano Zampini     PetscCall(DMLabelGetStratumBounds(label, ct, start, end));
85592827ebadSStefano Zampini   }
85603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8561e6139122SMatthew G. Knepley }
8562e6139122SMatthew G. Knepley 
8563d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8564d71ae5a4SJacob Faibussowitsch {
8565552f7358SJed Brown   PetscSection section, globalSection;
8566552f7358SJed Brown   PetscInt    *numbers, p;
8567552f7358SJed Brown 
8568552f7358SJed Brown   PetscFunctionBegin;
8569d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
85709566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
85719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
857248a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
85739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
85749566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
85759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8576552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
85779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8578ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8579ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8580552f7358SJed Brown   }
85819566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8582ef48cebcSMatthew G. Knepley   if (globalSize) {
8583ef48cebcSMatthew G. Knepley     PetscLayout layout;
85849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
85859566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
85869566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8587ef48cebcSMatthew G. Knepley   }
85889566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
85899566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
85903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8591552f7358SJed Brown }
8592552f7358SJed Brown 
8593d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8594d71ae5a4SJacob Faibussowitsch {
8595412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8596552f7358SJed Brown 
8597552f7358SJed Brown   PetscFunctionBegin;
85989566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
85999566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
86009566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
86019566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
86023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8603552f7358SJed Brown }
860481ed3555SMatthew G. Knepley 
86058dab3259SMatthew G. Knepley /*@
86067cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
86077cd05799SMatthew G. Knepley 
86087cd05799SMatthew G. Knepley   Input Parameter:
8609a1cb98faSBarry Smith . dm - The `DMPLEX` object
86107cd05799SMatthew G. Knepley 
86117cd05799SMatthew G. Knepley   Output Parameter:
86127cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
86137cd05799SMatthew G. Knepley 
86147cd05799SMatthew G. Knepley   Level: developer
86157cd05799SMatthew G. Knepley 
86161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
86177cd05799SMatthew G. Knepley @*/
8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8619d71ae5a4SJacob Faibussowitsch {
862081ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
862181ed3555SMatthew G. Knepley 
862281ed3555SMatthew G. Knepley   PetscFunctionBegin;
862381ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86249566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8625552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
86263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8627552f7358SJed Brown }
8628552f7358SJed Brown 
8629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8630d71ae5a4SJacob Faibussowitsch {
8631412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
863281ed3555SMatthew G. Knepley 
863381ed3555SMatthew G. Knepley   PetscFunctionBegin;
863481ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
86369566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
86373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
863881ed3555SMatthew G. Knepley }
863981ed3555SMatthew G. Knepley 
86408dab3259SMatthew G. Knepley /*@
86416aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
86427cd05799SMatthew G. Knepley 
86437cd05799SMatthew G. Knepley   Input Parameter:
8644a1cb98faSBarry Smith . dm - The `DMPLEX` object
86457cd05799SMatthew G. Knepley 
86467cd05799SMatthew G. Knepley   Output Parameter:
86477cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
86487cd05799SMatthew G. Knepley 
86497cd05799SMatthew G. Knepley   Level: developer
86507cd05799SMatthew G. Knepley 
86511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
86527cd05799SMatthew G. Knepley @*/
8653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8654d71ae5a4SJacob Faibussowitsch {
8655552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8656552f7358SJed Brown 
8657552f7358SJed Brown   PetscFunctionBegin;
8658552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86599566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8660552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
86613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8662552f7358SJed Brown }
8663552f7358SJed Brown 
86648dab3259SMatthew G. Knepley /*@
8665966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8666966484cfSJed Brown 
866720f4b53cSBarry Smith   Collective
86687cd05799SMatthew G. Knepley 
86697cd05799SMatthew G. Knepley   Input Parameter:
8670a1cb98faSBarry Smith . dm - The `DMPLEX` object
86717cd05799SMatthew G. Knepley 
86727cd05799SMatthew G. Knepley   Output Parameter:
86737cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
86747cd05799SMatthew G. Knepley 
8675a1cb98faSBarry Smith   Level: developer
8676966484cfSJed Brown 
8677a1cb98faSBarry Smith   Notes:
8678a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8679966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8680966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8681966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8682966484cfSJed Brown 
8683966484cfSJed Brown   The partitioned mesh is
8684966484cfSJed Brown   ```
8685966484cfSJed Brown   (2)--0--(3)--1--(4)    (1)--0--(2)
8686966484cfSJed Brown   ```
8687966484cfSJed Brown   and its global numbering is
8688966484cfSJed Brown   ```
8689966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8690966484cfSJed Brown   ```
8691966484cfSJed Brown   Then the global numbering is provided as
8692966484cfSJed Brown   ```
8693966484cfSJed Brown   [0] Number of indices in set 5
8694966484cfSJed Brown   [0] 0 0
8695966484cfSJed Brown   [0] 1 1
8696966484cfSJed Brown   [0] 2 3
8697966484cfSJed Brown   [0] 3 4
8698966484cfSJed Brown   [0] 4 -6
8699966484cfSJed Brown   [1] Number of indices in set 3
8700966484cfSJed Brown   [1] 0 2
8701966484cfSJed Brown   [1] 1 5
8702966484cfSJed Brown   [1] 2 6
8703966484cfSJed Brown   ```
8704966484cfSJed Brown 
87051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87067cd05799SMatthew G. Knepley @*/
8707d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8708d71ae5a4SJacob Faibussowitsch {
8709ef48cebcSMatthew G. Knepley   IS        nums[4];
8710862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8711ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
87120c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8713ef48cebcSMatthew G. Knepley 
8714ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8715ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
87170c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
87189566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
87190c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8720862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8721862913ffSStefano Zampini     PetscInt end;
8722862913ffSStefano Zampini 
8723862913ffSStefano Zampini     depths[d] = depth - d;
87249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
87250c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8726862913ffSStefano Zampini   }
87270c15888dSMatthew G. Knepley   if (empty)
87280c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
87290c15888dSMatthew G. Knepley       depths[d] = -1;
87300c15888dSMatthew G. Knepley       starts[d] = -1;
87310c15888dSMatthew G. Knepley     }
87320c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
87331c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8734ad540459SPierre Jolivet   for (d = 0; d <= depth; ++d) PetscCheck(starts[d] < 0 || depths[d] == gdepths[d], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected depth %" PetscInt_FMT ", found %" PetscInt_FMT, depths[d], gdepths[d]);
87350c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8736ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8737ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8738ef48cebcSMatthew G. Knepley 
87399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
87409566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8741ef48cebcSMatthew G. Knepley     shift += gsize;
8742ef48cebcSMatthew G. Knepley   }
8743d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
87449566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
87453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8746ef48cebcSMatthew G. Knepley }
8747ef48cebcSMatthew G. Knepley 
874808a22f4bSMatthew G. Knepley /*@
874908a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
875008a22f4bSMatthew G. Knepley 
875108a22f4bSMatthew G. Knepley   Input Parameter:
8752a1cb98faSBarry Smith . dm - The `DMPLEX` object
875308a22f4bSMatthew G. Knepley 
875408a22f4bSMatthew G. Knepley   Output Parameter:
875508a22f4bSMatthew G. Knepley . ranks - The rank field
875608a22f4bSMatthew G. Knepley 
8757a1cb98faSBarry Smith   Options Database Key:
875820f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
875908a22f4bSMatthew G. Knepley 
876008a22f4bSMatthew G. Knepley   Level: intermediate
876108a22f4bSMatthew G. Knepley 
87621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
876308a22f4bSMatthew G. Knepley @*/
8764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8765d71ae5a4SJacob Faibussowitsch {
876608a22f4bSMatthew G. Knepley   DM             rdm;
876708a22f4bSMatthew G. Knepley   PetscFE        fe;
876808a22f4bSMatthew G. Knepley   PetscScalar   *r;
876908a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8770a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
877108a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8772a55f9a55SMatthew G. Knepley   PetscBool      simplex;
877308a22f4bSMatthew G. Knepley 
877408a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8775f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87764f572ea9SToby Isaac   PetscAssertPointer(ranks, 2);
87779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
87789566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
87799566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
87809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
87819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8782a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
87839566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
87849566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
87859566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
87869566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
87879566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
87889566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
87899566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
87909566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
879108a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
879208a22f4bSMatthew G. Knepley     PetscScalar *lr;
879308a22f4bSMatthew G. Knepley 
87949566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
879571f09efeSPierre Jolivet     if (lr) *lr = rank;
879608a22f4bSMatthew G. Knepley   }
87979566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
87989566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
87993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
880008a22f4bSMatthew G. Knepley }
880108a22f4bSMatthew G. Knepley 
8802ca8062c8SMatthew G. Knepley /*@
880318e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
880418e14f0cSMatthew G. Knepley 
880518e14f0cSMatthew G. Knepley   Input Parameters:
880620f4b53cSBarry Smith + dm    - The `DMPLEX`
880720f4b53cSBarry Smith - label - The `DMLabel`
880818e14f0cSMatthew G. Knepley 
880918e14f0cSMatthew G. Knepley   Output Parameter:
881018e14f0cSMatthew G. Knepley . val - The label value field
881118e14f0cSMatthew G. Knepley 
881220f4b53cSBarry Smith   Options Database Key:
881320f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
881418e14f0cSMatthew G. Knepley 
881518e14f0cSMatthew G. Knepley   Level: intermediate
881618e14f0cSMatthew G. Knepley 
88171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
881818e14f0cSMatthew G. Knepley @*/
8819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8820d71ae5a4SJacob Faibussowitsch {
882118e14f0cSMatthew G. Knepley   DM           rdm;
882218e14f0cSMatthew G. Knepley   PetscFE      fe;
882318e14f0cSMatthew G. Knepley   PetscScalar *v;
882418e14f0cSMatthew G. Knepley   PetscInt     dim, cStart, cEnd, c;
882518e14f0cSMatthew G. Knepley 
882618e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
882718e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88284f572ea9SToby Isaac   PetscAssertPointer(label, 2);
88294f572ea9SToby Isaac   PetscAssertPointer(val, 3);
88309566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
88319566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
88329566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
88339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "label_value"));
88349566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
88359566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
88369566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
88379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
88389566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
88399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*val, "label_value"));
88409566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
884118e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
884218e14f0cSMatthew G. Knepley     PetscScalar *lv;
884318e14f0cSMatthew G. Knepley     PetscInt     cval;
884418e14f0cSMatthew G. Knepley 
88459566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
88469566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
884718e14f0cSMatthew G. Knepley     *lv = cval;
884818e14f0cSMatthew G. Knepley   }
88499566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
88509566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
88513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
885218e14f0cSMatthew G. Knepley }
885318e14f0cSMatthew G. Knepley 
885418e14f0cSMatthew G. Knepley /*@
8855ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8856ca8062c8SMatthew G. Knepley 
885769916449SMatthew G. Knepley   Input Parameter:
8858a1cb98faSBarry Smith . dm - The `DMPLEX` object
8859a1cb98faSBarry Smith 
8860a1cb98faSBarry Smith   Level: developer
8861ca8062c8SMatthew G. Knepley 
886295eb5ee5SVaclav Hapla   Notes:
886395eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
886495eb5ee5SVaclav Hapla 
886520f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8866ca8062c8SMatthew G. Knepley 
88671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8868ca8062c8SMatthew G. Knepley @*/
8869d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8870d71ae5a4SJacob Faibussowitsch {
8871ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8872ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8873ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
887457beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
887557beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8876ca8062c8SMatthew G. Knepley 
8877ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8878ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88799566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
88809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
88819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8882ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
88839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8884ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
88859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
88869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8887ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
888842e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
888942e66dfaSMatthew G. Knepley       PetscInt  d;
889042e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
88919371c9d4SSatish Balay         if (cone[c] == cone[d]) {
88929371c9d4SSatish Balay           dup = PETSC_TRUE;
88939371c9d4SSatish Balay           break;
88949371c9d4SSatish Balay         }
889542e66dfaSMatthew G. Knepley       }
88969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
88979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8898ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8899ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8900ca8062c8SMatthew G. Knepley       }
890142e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
890263a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
890348a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
89049566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
890563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
890648a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
89079566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
890863a3b9bcSJacob Faibussowitsch         PetscCheck(!dup, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not repeatedly found in support of repeated cone point %" PetscInt_FMT, p, cone[c]);
8909f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8910ca8062c8SMatthew G. Knepley       }
891142e66dfaSMatthew G. Knepley     }
89129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
89139371c9d4SSatish Balay     if (p != pp) {
89149371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
89159371c9d4SSatish Balay       continue;
89169371c9d4SSatish Balay     }
89179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
89189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8919ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
89209566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
89219566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8922ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
89239566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
89249371c9d4SSatish Balay         if (cone[c] != pp) {
89259371c9d4SSatish Balay           c = 0;
89269371c9d4SSatish Balay           break;
89279371c9d4SSatish Balay         }
8928ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8929ca8062c8SMatthew G. Knepley       }
8930ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
893163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
893248a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
89339566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
893463a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
893548a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
89369566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
893763a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8938ca8062c8SMatthew G. Knepley       }
8939ca8062c8SMatthew G. Knepley     }
8940ca8062c8SMatthew G. Knepley   }
894157beb4faSStefano Zampini   if (storagecheck) {
89429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
89439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
894463a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
894557beb4faSStefano Zampini   }
89463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8947ca8062c8SMatthew G. Knepley }
8948ca8062c8SMatthew G. Knepley 
8949412e9a14SMatthew G. Knepley /*
8950412e9a14SMatthew 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.
8951412e9a14SMatthew G. Knepley */
8952d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8953d71ae5a4SJacob Faibussowitsch {
8954412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8955412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8956412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8957412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8958412e9a14SMatthew G. Knepley 
8959412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8960412e9a14SMatthew G. Knepley   *unsplit = 0;
8961412e9a14SMatthew G. Knepley   switch (ct) {
8962d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
8963d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
8964d71ae5a4SJacob Faibussowitsch     break;
8965412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
89669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
89679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8968412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
89699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8970412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8971412e9a14SMatthew G. Knepley     }
8972412e9a14SMatthew G. Knepley     break;
8973412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
8974412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
89759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
89769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8977412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
89789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
89799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8980412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
89819566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8982412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8983412e9a14SMatthew G. Knepley           PetscInt p;
89849371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
89859371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
8986412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
8987412e9a14SMatthew G. Knepley         }
8988412e9a14SMatthew G. Knepley       }
8989412e9a14SMatthew G. Knepley     }
8990412e9a14SMatthew G. Knepley     break;
8991d71ae5a4SJacob Faibussowitsch   default:
8992d71ae5a4SJacob Faibussowitsch     break;
8993412e9a14SMatthew G. Knepley   }
8994412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
89959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8996412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8997412e9a14SMatthew G. Knepley   }
89983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8999412e9a14SMatthew G. Knepley }
9000412e9a14SMatthew G. Knepley 
9001ca8062c8SMatthew G. Knepley /*@
9002ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
9003ca8062c8SMatthew G. Knepley 
9004ca8062c8SMatthew G. Knepley   Input Parameters:
9005a1cb98faSBarry Smith + dm         - The `DMPLEX` object
900658723a97SMatthew G. Knepley - cellHeight - Normally 0
9007ca8062c8SMatthew G. Knepley 
9008a1cb98faSBarry Smith   Level: developer
9009a1cb98faSBarry Smith 
901095eb5ee5SVaclav Hapla   Notes:
901195eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
901225c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
9013ca8062c8SMatthew G. Knepley 
901420f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
901595eb5ee5SVaclav Hapla 
90161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9017ca8062c8SMatthew G. Knepley @*/
9018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
9019d71ae5a4SJacob Faibussowitsch {
9020412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
9021412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
9022412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
9023ca8062c8SMatthew G. Knepley 
9024ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9025ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90269566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
90279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
90289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9029412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9030412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
9031412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
903258723a97SMatthew G. Knepley 
90339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
903463a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
9035412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
9036412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
90379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
903863a3b9bcSJacob Faibussowitsch       PetscCheck(coneSize == DMPolytopeTypeGetConeSize(ct), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has cone size %" PetscInt_FMT " != %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct));
9039412e9a14SMatthew G. Knepley     }
90409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
904158723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
904258723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
9043412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
904458723a97SMatthew G. Knepley     }
90459566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
9046412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
9047412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
9048412e9a14SMatthew G. Knepley       PetscInt unsplit;
904942363296SMatthew G. Knepley 
90509566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9051412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
905242363296SMatthew G. Knepley     }
905363a3b9bcSJacob Faibussowitsch     PetscCheck(Nv == DMPolytopeTypeGetNumVertices(ct), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices != %" PetscInt_FMT, c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct));
905442363296SMatthew G. Knepley   }
90553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9056ca8062c8SMatthew G. Knepley }
90579bf0dad6SMatthew G. Knepley 
90589bf0dad6SMatthew G. Knepley /*@
90599bf0dad6SMatthew 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
90609bf0dad6SMatthew G. Knepley 
906120f4b53cSBarry Smith   Collective
9062899ea2b8SJacob Faibussowitsch 
90639bf0dad6SMatthew G. Knepley   Input Parameters:
9064a1cb98faSBarry Smith + dm         - The `DMPLEX` object
90659bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
90669bf0dad6SMatthew G. Knepley 
9067a1cb98faSBarry Smith   Level: developer
9068a1cb98faSBarry Smith 
906945da879fSVaclav Hapla   Notes:
907045da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
907145da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
907245da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
907345da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
90749bf0dad6SMatthew G. Knepley 
9075a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
907695eb5ee5SVaclav Hapla 
90771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
90789bf0dad6SMatthew G. Knepley @*/
9079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
9080d71ae5a4SJacob Faibussowitsch {
9081ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
9082899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
90839bf0dad6SMatthew G. Knepley 
90849bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
90859bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90868f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
90873ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
90888f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
90893ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
90903ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9091899ea2b8SJacob Faibussowitsch   }
9092899ea2b8SJacob Faibussowitsch 
90939566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
90949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
90959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9096ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
90979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
90983554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
9099412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
9100412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
9101ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
9102412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
9103412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
91049bf0dad6SMatthew G. Knepley 
91059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
91069566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9107412e9a14SMatthew G. Knepley       if (unsplit) continue;
91089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
91099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
91109566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
91119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
91129bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
91139bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
91149bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
91159bf0dad6SMatthew G. Knepley       }
91169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
911763a3b9bcSJacob Faibussowitsch       PetscCheck(coneSize == numFaces, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " faces but should have %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, numFaces);
91189bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
9119d4961f80SStefano Zampini         DMPolytopeType fct;
91209bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
91219bf0dad6SMatthew G. Knepley 
91229566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
91239566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
91249bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
91259bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
91269bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
91279bf0dad6SMatthew G. Knepley         }
912863a3b9bcSJacob Faibussowitsch         PetscCheck(fnumCorners == faceSizes[f], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices but should have %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]);
91299bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
9130b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
9131b5a892a1SMatthew G. Knepley             PetscInt v1;
9132b5a892a1SMatthew G. Knepley 
91339566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
913463a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
91359566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
913663a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
91379566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
913863a3b9bcSJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ", ornt %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s vertex %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff + v]);
9139b5a892a1SMatthew G. Knepley           }
91409bf0dad6SMatthew G. Knepley         }
91419566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
9142412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
91439bf0dad6SMatthew G. Knepley       }
91449566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
91459566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
91469bf0dad6SMatthew G. Knepley     }
91473554e41dSMatthew G. Knepley   }
91483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9149552f7358SJed Brown }
91503913d7c8SMatthew G. Knepley 
9151bb6a34a8SMatthew G. Knepley /*@
9152bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
9153bb6a34a8SMatthew G. Knepley 
9154bb6a34a8SMatthew G. Knepley   Input Parameter:
9155a1cb98faSBarry Smith . dm - The `DMPLEX` object
9156a1cb98faSBarry Smith 
9157a1cb98faSBarry Smith   Level: developer
9158bb6a34a8SMatthew G. Knepley 
915995eb5ee5SVaclav Hapla   Notes:
916095eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
916195eb5ee5SVaclav Hapla 
916220f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9163bb6a34a8SMatthew G. Knepley 
91641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9165bb6a34a8SMatthew G. Knepley @*/
9166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
9167d71ae5a4SJacob Faibussowitsch {
9168a2a9e04cSMatthew G. Knepley   Vec       coordinates;
9169bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
9170bb6a34a8SMatthew G. Knepley   PetscReal vol;
917151a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
9172bb6a34a8SMatthew G. Knepley 
9173bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
91749566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
91759566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
91763ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
91779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
9178bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
91799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
9180a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
91819566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
91823ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
9183412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9184412e9a14SMatthew G. Knepley     DMPolytopeType ct;
9185412e9a14SMatthew G. Knepley     PetscInt       unsplit;
9186412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
9187412e9a14SMatthew G. Knepley 
91889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
9189412e9a14SMatthew G. Knepley     switch (ct) {
9190412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
9191412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9192d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9193d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
9194d71ae5a4SJacob Faibussowitsch       break;
9195d71ae5a4SJacob Faibussowitsch     default:
9196d71ae5a4SJacob Faibussowitsch       break;
9197412e9a14SMatthew G. Knepley     }
9198412e9a14SMatthew G. Knepley     switch (ct) {
9199412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
9200412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9201412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9202d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
9203d71ae5a4SJacob Faibussowitsch       continue;
9204d71ae5a4SJacob Faibussowitsch     default:
9205d71ae5a4SJacob Faibussowitsch       break;
9206412e9a14SMatthew G. Knepley     }
92079566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9208412e9a14SMatthew G. Knepley     if (unsplit) continue;
92099566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
92101dca8a05SBarry Smith     PetscCheck(detJ >= -PETSC_SMALL && (detJ > 0.0 || ignoreZeroVol), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double)detJ);
921163a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
92126858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
92136858538eSMatthew G. Knepley     if (depth > 1) {
92149566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
92151dca8a05SBarry Smith       PetscCheck(vol >= -PETSC_SMALL && (vol > 0.0 || ignoreZeroVol), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double)vol);
921663a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9217bb6a34a8SMatthew G. Knepley     }
9218bb6a34a8SMatthew G. Knepley   }
92193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9220bb6a34a8SMatthew G. Knepley }
9221bb6a34a8SMatthew G. Knepley 
922203da9461SVaclav Hapla /*@
922320f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
92247726db96SVaclav Hapla 
922520f4b53cSBarry Smith   Collective
922603da9461SVaclav Hapla 
922703da9461SVaclav Hapla   Input Parameters:
9228a1cb98faSBarry Smith + dm              - The `DMPLEX` object
922920f4b53cSBarry Smith . pointSF         - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9230a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9231a1cb98faSBarry Smith 
9232a1cb98faSBarry Smith   Level: developer
923303da9461SVaclav Hapla 
9234e83a0d2dSVaclav Hapla   Notes:
9235e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
923603da9461SVaclav Hapla 
9237a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
923895eb5ee5SVaclav Hapla 
9239baca6076SPierre Jolivet   Extra roots can come from periodic cuts, where additional points appear on the boundary
9240d7d32a9aSMatthew G. Knepley 
92411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
924203da9461SVaclav Hapla @*/
9243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9244d71ae5a4SJacob Faibussowitsch {
92457726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
92467726db96SVaclav Hapla   const PetscInt    *locals;
92477726db96SVaclav Hapla   const PetscSFNode *remotes;
9248f0cfc026SVaclav Hapla   PetscBool          distributed;
92497726db96SVaclav Hapla   MPI_Comm           comm;
92507726db96SVaclav Hapla   PetscMPIInt        rank;
925103da9461SVaclav Hapla 
925203da9461SVaclav Hapla   PetscFunctionBegin;
925303da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92547726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
92557726db96SVaclav Hapla   else pointSF = dm->sf;
92567726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
92577726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
92587726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
92597726db96SVaclav Hapla   {
92607726db96SVaclav Hapla     PetscMPIInt mpiFlag;
92617726db96SVaclav Hapla 
92627726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
92637726db96SVaclav Hapla     PetscCheck(mpiFlag == MPI_CONGRUENT || mpiFlag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "DM and Point SF have different communicators (flag %d)", mpiFlag);
92647726db96SVaclav Hapla   }
92657726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
92669566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
92677726db96SVaclav Hapla   if (!distributed) {
92687726db96SVaclav Hapla     PetscCheck(nroots < 0 || nleaves == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Undistributed DMPlex cannot have non-empty PointSF (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves);
92693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
92708918e3e2SVaclav Hapla   }
92717726db96SVaclav Hapla   PetscCheck(nroots >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves);
92727726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
927303da9461SVaclav Hapla 
92747726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
92757726db96SVaclav Hapla   {
92767726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
92777726db96SVaclav Hapla 
92787726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
92797726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9280d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
92817726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
92827726db96SVaclav Hapla   }
92837726db96SVaclav Hapla 
92847726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
92857726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
92867726db96SVaclav Hapla     PetscAssert(remotes[l].rank != (PetscInt)rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%" PetscInt_FMT ",%" PetscInt_FMT ")", locals ? locals[l] : l, remotes[l].rank, remotes[l].index);
92877726db96SVaclav Hapla   }
92887726db96SVaclav Hapla 
92897726db96SVaclav Hapla   /* Check there are no cells in interface */
92907726db96SVaclav Hapla   if (!overlap) {
92917726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
92927726db96SVaclav Hapla 
92939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
92949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9295f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
92967726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9297f5869d18SMatthew G. Knepley 
92987726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
92997726db96SVaclav Hapla     }
930003da9461SVaclav Hapla   }
9301ece87651SVaclav Hapla 
93027726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
93037726db96SVaclav Hapla   {
93047726db96SVaclav Hapla     const PetscInt *rootdegree;
93057726db96SVaclav Hapla 
93067726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
93077726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9308f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
93097726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9310f5869d18SMatthew G. Knepley       const PetscInt *cone;
9311f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9312f5869d18SMatthew G. Knepley 
93139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
93149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9315f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9316f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
93177726db96SVaclav Hapla           if (locals) {
93189566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
93197726db96SVaclav Hapla           } else {
93207726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
93217726db96SVaclav Hapla           }
932263a3b9bcSJacob Faibussowitsch           PetscCheck(idx >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " but not %" PetscInt_FMT " from its cone", point, cone[c]);
9323f5869d18SMatthew G. Knepley         }
9324f5869d18SMatthew G. Knepley       }
9325ece87651SVaclav Hapla     }
93267726db96SVaclav Hapla   }
93273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
932803da9461SVaclav Hapla }
932903da9461SVaclav Hapla 
93307f9d8d6cSVaclav Hapla /*@
933120f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
93327f9d8d6cSVaclav Hapla 
93337f9d8d6cSVaclav Hapla   Input Parameter:
9334a1cb98faSBarry Smith . dm - The `DMPLEX` object
9335a1cb98faSBarry Smith 
9336a1cb98faSBarry Smith   Level: developer
93377f9d8d6cSVaclav Hapla 
93387f9d8d6cSVaclav Hapla   Notes:
93397f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
93407f9d8d6cSVaclav Hapla 
934120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
93427f9d8d6cSVaclav Hapla 
934320f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
93447f9d8d6cSVaclav Hapla 
93451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
93467f9d8d6cSVaclav Hapla @*/
9347d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9348d71ae5a4SJacob Faibussowitsch {
93497f9d8d6cSVaclav Hapla   PetscInt cellHeight;
93507f9d8d6cSVaclav Hapla 
9351b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
93527f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
93539566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
93549566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
93559566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
93569566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9357d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
93589566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
93593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9360b5a892a1SMatthew G. Knepley }
9361b5a892a1SMatthew G. Knepley 
93629371c9d4SSatish Balay typedef struct cell_stats {
9363068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9364068a5610SStefano Zampini   PetscInt  count;
9365068a5610SStefano Zampini } cell_stats_t;
9366068a5610SStefano Zampini 
9367d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9368d71ae5a4SJacob Faibussowitsch {
9369068a5610SStefano Zampini   PetscInt i, N = *len;
9370068a5610SStefano Zampini 
9371068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9372068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9373068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9374068a5610SStefano Zampini 
9375068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9376068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9377068a5610SStefano Zampini     B->sum += A->sum;
9378068a5610SStefano Zampini     B->squaresum += A->squaresum;
9379068a5610SStefano Zampini     B->count += A->count;
9380068a5610SStefano Zampini   }
9381068a5610SStefano Zampini }
9382068a5610SStefano Zampini 
9383068a5610SStefano Zampini /*@
938443fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9385068a5610SStefano Zampini 
938620f4b53cSBarry Smith   Collective
93878261a58bSMatthew G. Knepley 
9388068a5610SStefano Zampini   Input Parameters:
9389a1cb98faSBarry Smith + dm        - The `DMPLEX` object
939020f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9391a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9392a1cb98faSBarry Smith 
9393a1cb98faSBarry Smith   Level: developer
9394068a5610SStefano Zampini 
939595eb5ee5SVaclav Hapla   Notes:
939695eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
939795eb5ee5SVaclav Hapla 
9398a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9399068a5610SStefano Zampini 
94001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9401068a5610SStefano Zampini @*/
9402d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9403d71ae5a4SJacob Faibussowitsch {
9404068a5610SStefano Zampini   DM           dmCoarse;
940543fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
940643fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
940743fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
940843fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9409412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
941043fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9411068a5610SStefano Zampini 
9412068a5610SStefano Zampini   PetscFunctionBegin;
9413068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9414068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9415068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9416068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9417068a5610SStefano Zampini   stats.count                 = 0;
9418068a5610SStefano Zampini 
94199566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
94209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
94219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
94229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
94239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
94249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9425412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9426068a5610SStefano Zampini     PetscInt  i;
9427068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9428068a5610SStefano Zampini 
94299566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
943063a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
943143fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9432068a5610SStefano Zampini       frobJ += J[i] * J[i];
9433068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9434068a5610SStefano Zampini     }
9435068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9436068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9437068a5610SStefano Zampini 
9438068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9439068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9440068a5610SStefano Zampini     stats.sum += cond;
9441068a5610SStefano Zampini     stats.squaresum += cond2;
9442068a5610SStefano Zampini     stats.count++;
94438261a58bSMatthew G. Knepley     if (output && cond > limit) {
944443fa8764SMatthew G. Knepley       PetscSection coordSection;
944543fa8764SMatthew G. Knepley       Vec          coordsLocal;
944643fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
944743fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
944843fa8764SMatthew G. Knepley 
94499566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
94509566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
94519566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
945263a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
945343fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
945463a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
945543fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
94569566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
94579566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
945843fa8764SMatthew G. Knepley         }
94599566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
946043fa8764SMatthew G. Knepley       }
94619566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
946243fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
946343fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
946443fa8764SMatthew G. Knepley 
946543fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
946643fa8764SMatthew G. Knepley           PetscReal len;
946743fa8764SMatthew G. Knepley 
94689566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
946963a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
947043fa8764SMatthew G. Knepley         }
947143fa8764SMatthew G. Knepley       }
94729566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
94739566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
947443fa8764SMatthew G. Knepley     }
9475068a5610SStefano Zampini   }
94769566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9477068a5610SStefano Zampini 
9478068a5610SStefano Zampini   if (size > 1) {
9479068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9480068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9481068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9482068a5610SStefano Zampini     MPI_Op       statReduce;
9483068a5610SStefano Zampini 
94849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
94859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
94869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
94879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
94889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
94899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9490068a5610SStefano Zampini   } else {
94919566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9492068a5610SStefano Zampini   }
9493dd400576SPatrick Sanan   if (rank == 0) {
9494068a5610SStefano Zampini     count = globalStats.count;
9495068a5610SStefano Zampini     min   = globalStats.min;
9496068a5610SStefano Zampini     max   = globalStats.max;
9497068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9498068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9499068a5610SStefano Zampini   }
9500068a5610SStefano Zampini 
950148a46eb9SPierre Jolivet   if (output) PetscCall(PetscPrintf(comm, "Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double)min, (double)max, (double)mean, (double)stdev));
95029566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9503068a5610SStefano Zampini 
95049566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9505068a5610SStefano Zampini   if (dmCoarse) {
9506068a5610SStefano Zampini     PetscBool isplex;
9507068a5610SStefano Zampini 
95089566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
95091baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9510068a5610SStefano Zampini   }
95113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9512068a5610SStefano Zampini }
9513068a5610SStefano Zampini 
9514f108dbd7SJacob Faibussowitsch /*@
9515f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9516f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9517f108dbd7SJacob Faibussowitsch 
951820f4b53cSBarry Smith   Collective
9519f108dbd7SJacob Faibussowitsch 
9520f108dbd7SJacob Faibussowitsch   Input Parameters:
9521a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9522a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9523f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9524f108dbd7SJacob Faibussowitsch 
9525f108dbd7SJacob Faibussowitsch   Output Parameters:
952620f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9527a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9528f108dbd7SJacob Faibussowitsch 
9529f108dbd7SJacob Faibussowitsch   Options Database Keys:
9530a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9531f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view   - view OrthQual vector.
9532f108dbd7SJacob Faibussowitsch 
9533a1cb98faSBarry Smith   Level: intermediate
9534a1cb98faSBarry Smith 
9535f108dbd7SJacob Faibussowitsch   Notes:
9536a4e35b19SJacob Faibussowitsch   Orthogonal quality is given by the following formula\:
9537f108dbd7SJacob Faibussowitsch 
9538a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9539f108dbd7SJacob Faibussowitsch 
9540f108dbd7SJacob 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
9541f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9542f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9543f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9544f108dbd7SJacob Faibussowitsch 
9545f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9546f108dbd7SJacob Faibussowitsch 
9547a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9548f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9549f108dbd7SJacob Faibussowitsch 
9550f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9551f108dbd7SJacob Faibussowitsch 
95521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9553f108dbd7SJacob Faibussowitsch @*/
9554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9555d71ae5a4SJacob Faibussowitsch {
95566ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
95576ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
95586ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9559f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
95606ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9561f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9562f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9563f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9564f108dbd7SJacob Faibussowitsch   IS                     glob;
9565f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9566f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9567f108dbd7SJacob Faibussowitsch 
9568f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9569f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9570ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
95714f572ea9SToby Isaac   PetscAssertPointer(OrthQual, 4);
95726bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
95739566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
95749566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
957563a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
95766ed19f2fSJacob Faibussowitsch   {
95776ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
95786ed19f2fSJacob Faibussowitsch 
95799566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9580f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9581f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9582f108dbd7SJacob Faibussowitsch 
95839566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
958498921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9585f108dbd7SJacob Faibussowitsch     }
95866ed19f2fSJacob Faibussowitsch   }
9587f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
95884f572ea9SToby Isaac     PetscAssertPointer(OrthQualLabel, 5);
95899566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
95909566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
95919371c9d4SSatish Balay   } else {
95929371c9d4SSatish Balay     *OrthQualLabel = NULL;
95939371c9d4SSatish Balay   }
95949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
95959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
95969566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
95979566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
95989566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
95999566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
96009566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
96019566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
96029566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
96039566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
96049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
96059566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
96069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
96079566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
96089566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
96099566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
96109566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
96119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
96126ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
96136ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9614f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9615f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9616898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9617f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9618f108dbd7SJacob Faibussowitsch 
96196ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9620f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9621f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
96229566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
96239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9624f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
96259566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
96266ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
96276ed19f2fSJacob Faibussowitsch       PetscInt         i;
96286ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9629f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9630f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9631f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9632f108dbd7SJacob Faibussowitsch 
9633f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9634f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
96359566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9636f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
96376ed19f2fSJacob Faibussowitsch       {
96386ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
96396ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
96406ed19f2fSJacob Faibussowitsch 
96419566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
96429566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
96439566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
96446ed19f2fSJacob Faibussowitsch       }
9645f108dbd7SJacob Faibussowitsch 
9646f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9647f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9648f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9649f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9650f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9651addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9652addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9653addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9654f108dbd7SJacob Faibussowitsch       }
9655addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9656addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9657addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9658f108dbd7SJacob Faibussowitsch 
9659f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9660f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9661f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9662f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9663f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9664f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9665f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9666f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9667f108dbd7SJacob Faibussowitsch       }
9668ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9669ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9670f108dbd7SJacob Faibussowitsch     }
96719566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
96729566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9673f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
96746ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9675f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
96769566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9677f108dbd7SJacob Faibussowitsch     }
9678f108dbd7SJacob Faibussowitsch   }
96799566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
96809566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
96819566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
96829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
96839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
96849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9685f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
96869566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9687f108dbd7SJacob Faibussowitsch   }
96889566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
9689cd791dc2SBarry Smith   PetscCall(PetscOptionsRestoreViewer(&vwr));
96909566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
96913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9692f108dbd7SJacob Faibussowitsch }
9693f108dbd7SJacob Faibussowitsch 
9694d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
96951eb70e55SToby Isaac  * interpolator construction */
9696d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9697d71ae5a4SJacob Faibussowitsch {
96981eb70e55SToby Isaac   PetscSection section, newSection, gsection;
96991eb70e55SToby Isaac   PetscSF      sf;
97001eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
97011eb70e55SToby Isaac 
97021eb70e55SToby Isaac   PetscFunctionBegin;
97031eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97044f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
97059566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
97069566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9707712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
97081eb70e55SToby Isaac   if (!ghasConstraints) {
97099566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
97101eb70e55SToby Isaac     *odm = dm;
97113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
97121eb70e55SToby Isaac   }
97139566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
97149566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
97159566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
97169566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
97179566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
97189566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
97199566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
97203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97211eb70e55SToby Isaac }
97221eb70e55SToby Isaac 
9723d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9724d71ae5a4SJacob Faibussowitsch {
97251eb70e55SToby Isaac   DM        dmco, dmfo;
97261eb70e55SToby Isaac   Mat       interpo;
97271eb70e55SToby Isaac   Vec       rscale;
97281eb70e55SToby Isaac   Vec       cglobalo, clocal;
97291eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
97301eb70e55SToby Isaac   PetscBool regular;
97311eb70e55SToby Isaac 
97321eb70e55SToby Isaac   PetscFunctionBegin;
97339566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
97349566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
97359566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
97369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
97379566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
97389566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
97399566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
97409566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
97419566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
97429566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
97439566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
97449566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
97459566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
97469566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
97479566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
97489566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
97499566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
97509566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
97519566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
97529566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
97539566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
97549566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
97559566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
97569566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
97571eb70e55SToby Isaac   *shift = fglobal;
97589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
97599566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
97609566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
97619566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
97629566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
97639566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
97649566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
97659566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
97663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97671eb70e55SToby Isaac }
97681eb70e55SToby Isaac 
9769d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9770d71ae5a4SJacob Faibussowitsch {
97711eb70e55SToby Isaac   PetscObject shifto;
97721eb70e55SToby Isaac   Vec         shift;
97731eb70e55SToby Isaac 
97741eb70e55SToby Isaac   PetscFunctionBegin;
97751eb70e55SToby Isaac   if (!interp) {
97761eb70e55SToby Isaac     Vec rscale;
97771eb70e55SToby Isaac 
97789566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
97799566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
97801eb70e55SToby Isaac   } else {
97819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
97821eb70e55SToby Isaac   }
97839566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
97841eb70e55SToby Isaac   if (!shifto) {
97859566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
97869566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
97871eb70e55SToby Isaac     shifto = (PetscObject)shift;
97889566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
97891eb70e55SToby Isaac   }
97901eb70e55SToby Isaac   shift = (Vec)shifto;
97919566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
97929566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
97939566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
97943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97951eb70e55SToby Isaac }
97961eb70e55SToby Isaac 
9797bceba477SMatthew G. Knepley /* Pointwise interpolation
9798bceba477SMatthew G. Knepley      Just code FEM for now
9799bceba477SMatthew G. Knepley      u^f = I u^c
98004ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
98014ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
98024ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9803bceba477SMatthew G. Knepley */
9804d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9805d71ae5a4SJacob Faibussowitsch {
9806bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9807bceba477SMatthew G. Knepley   PetscInt     m, n;
9808a063dac3SMatthew G. Knepley   void        *ctx;
980968132eb9SMatthew G. Knepley   DM           cdm;
9810cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9811bceba477SMatthew G. Knepley 
9812bceba477SMatthew G. Knepley   PetscFunctionBegin;
98139566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
98149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
98159566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
98169566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
981768132eb9SMatthew G. Knepley 
98189566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
98199566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
98209566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
98219566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
98229566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
982368132eb9SMatthew G. Knepley 
98249566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
98259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
98269566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
98279566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
98289566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
98294db47ee9SStefano Zampini   if (scaling) {
98305d1c2e58SMatthew G. Knepley     /* Use naive scaling */
98319566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
98324db47ee9SStefano Zampini   }
98333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9834a063dac3SMatthew G. Knepley }
9835bceba477SMatthew G. Knepley 
9836d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9837d71ae5a4SJacob Faibussowitsch {
98386dbf9973SLawrence Mitchell   VecScatter ctx;
983990748bafSMatthew G. Knepley 
9840a063dac3SMatthew G. Knepley   PetscFunctionBegin;
98419566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
98429566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
98439566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
98443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9845bceba477SMatthew G. Knepley }
9846bceba477SMatthew G. Knepley 
9847d71ae5a4SJacob Faibussowitsch static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
9848d71ae5a4SJacob Faibussowitsch {
984900635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
985000635df3SMatthew G. Knepley   PetscInt       c;
985100635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
98523e9753d6SMatthew G. Knepley }
98533e9753d6SMatthew G. Knepley 
9854d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9855d71ae5a4SJacob Faibussowitsch {
9856b4937a87SMatthew G. Knepley   DM           dmc;
9857b4937a87SMatthew G. Knepley   PetscDS      ds;
9858b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9859b4937a87SMatthew G. Knepley   IS           cellIS;
9860b4937a87SMatthew G. Knepley   PetscFormKey key;
9861b4937a87SMatthew G. Knepley   PetscInt     depth;
9862b4937a87SMatthew G. Knepley 
9863b4937a87SMatthew G. Knepley   PetscFunctionBegin;
98649566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
98659566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
98669566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
98679566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
98689566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
98699566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
98709566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
98719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
98729566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
98739566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
98749566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9875b4937a87SMatthew G. Knepley   key.label = NULL;
9876b4937a87SMatthew G. Knepley   key.value = 0;
9877b4937a87SMatthew G. Knepley   key.field = 0;
9878b4937a87SMatthew G. Knepley   key.part  = 0;
98799566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
98809566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
98819566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
98829566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
98839566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
98849566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
98859566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
98869566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
98873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9888b4937a87SMatthew G. Knepley }
9889b4937a87SMatthew G. Knepley 
9890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9891d71ae5a4SJacob Faibussowitsch {
9892bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9893bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9894bd041c0cSMatthew G. Knepley   void        *ctx;
9895bd041c0cSMatthew G. Knepley   DM           cdm;
9896bd041c0cSMatthew G. Knepley   PetscBool    regular;
9897bd041c0cSMatthew G. Knepley 
9898bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
98993e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
99003e9753d6SMatthew G. Knepley     DM            dmc;
99013e9753d6SMatthew G. Knepley     PetscDS       ds;
9902b4937a87SMatthew G. Knepley     PetscWeakForm wf;
99033e9753d6SMatthew G. Knepley     Vec           u;
99043e9753d6SMatthew G. Knepley     IS            cellIS;
990506ad1575SMatthew G. Knepley     PetscFormKey  key;
99063e9753d6SMatthew G. Knepley     PetscInt      depth;
99073e9753d6SMatthew G. Knepley 
99089566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
99099566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
99109566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
99119566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
99129566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
99139566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
99149566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
99158d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
99169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
99179566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
99189566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
99196528b96dSMatthew G. Knepley     key.label = NULL;
99206528b96dSMatthew G. Knepley     key.value = 0;
99216528b96dSMatthew G. Knepley     key.field = 0;
992206ad1575SMatthew G. Knepley     key.part  = 0;
99239566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
99249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
99258d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
99269566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
99273e9753d6SMatthew G. Knepley   } else {
99289566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
99299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
99309566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
99319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9932bd041c0cSMatthew G. Knepley 
99339566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
99349566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
99359566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
99369566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9937bd041c0cSMatthew G. Knepley 
99389566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
99399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
99409566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
99419566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
99423e9753d6SMatthew G. Knepley   }
99439566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
99443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9945bd041c0cSMatthew G. Knepley }
9946bd041c0cSMatthew G. Knepley 
99470aef6b92SMatthew G. Knepley /*@
99480aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
99490aef6b92SMatthew G. Knepley 
99500aef6b92SMatthew G. Knepley   Input Parameter:
9951a1cb98faSBarry Smith . dm - The `DMPLEX` object
99520aef6b92SMatthew G. Knepley 
99530aef6b92SMatthew G. Knepley   Output Parameter:
99540aef6b92SMatthew G. Knepley . regular - The flag
99550aef6b92SMatthew G. Knepley 
99560aef6b92SMatthew G. Knepley   Level: intermediate
99570aef6b92SMatthew G. Knepley 
99581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
99590aef6b92SMatthew G. Knepley @*/
9960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
9961d71ae5a4SJacob Faibussowitsch {
99620aef6b92SMatthew G. Knepley   PetscFunctionBegin;
99630aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99644f572ea9SToby Isaac   PetscAssertPointer(regular, 2);
99650aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
99663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99670aef6b92SMatthew G. Knepley }
99680aef6b92SMatthew G. Knepley 
99690aef6b92SMatthew G. Knepley /*@
99700aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
99710aef6b92SMatthew G. Knepley 
99720aef6b92SMatthew G. Knepley   Input Parameters:
9973a1cb98faSBarry Smith + dm      - The `DMPLEX` object
99740aef6b92SMatthew G. Knepley - regular - The flag
99750aef6b92SMatthew G. Knepley 
99760aef6b92SMatthew G. Knepley   Level: intermediate
99770aef6b92SMatthew G. Knepley 
99781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
99790aef6b92SMatthew G. Knepley @*/
9980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
9981d71ae5a4SJacob Faibussowitsch {
99820aef6b92SMatthew G. Knepley   PetscFunctionBegin;
99830aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99840aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
99853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99860aef6b92SMatthew G. Knepley }
99870aef6b92SMatthew G. Knepley 
9988a68b90caSToby Isaac /*@
9989f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9990a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
9991a68b90caSToby Isaac 
9992a1cb98faSBarry Smith   Not Collective
9993a68b90caSToby Isaac 
9994f899ff85SJose E. Roman   Input Parameter:
9995a1cb98faSBarry Smith . dm - The `DMPLEX` object
9996a68b90caSToby Isaac 
9997a68b90caSToby Isaac   Output Parameters:
999820f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
999920f4b53cSBarry Smith - anchorIS      - If not `NULL`, set to the list of anchors indexed by `anchorSection`
10000a68b90caSToby Isaac 
10001a68b90caSToby Isaac   Level: intermediate
10002a68b90caSToby Isaac 
100031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
10004a68b90caSToby Isaac @*/
10005d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
10006d71ae5a4SJacob Faibussowitsch {
10007a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
10008a68b90caSToby Isaac 
10009a68b90caSToby Isaac   PetscFunctionBegin;
10010a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100119566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
10012a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
10013a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
100143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10015a68b90caSToby Isaac }
10016a68b90caSToby Isaac 
10017a68b90caSToby Isaac /*@
10018a4e35b19SJacob Faibussowitsch   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.
10019a68b90caSToby Isaac 
1002020f4b53cSBarry Smith   Collective
10021a68b90caSToby Isaac 
10022a68b90caSToby Isaac   Input Parameters:
10023a1cb98faSBarry Smith + dm            - The `DMPLEX` object
10024a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
10025a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10026a1cb98faSBarry Smith - anchorIS      - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10027a68b90caSToby Isaac 
10028a68b90caSToby Isaac   Level: intermediate
10029a68b90caSToby Isaac 
10030a1cb98faSBarry Smith   Notes:
10031a4e35b19SJacob Faibussowitsch   Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to
10032a4e35b19SJacob Faibussowitsch   an outside value, the anchor constraints set a point's degrees of freedom to be a linear
10033a4e35b19SJacob Faibussowitsch   combination of other points' degrees of freedom.
10034a4e35b19SJacob Faibussowitsch 
10035a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
10036a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
10037a1cb98faSBarry Smith 
1003820f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
10039a1cb98faSBarry Smith 
100401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
10041a68b90caSToby Isaac @*/
10042d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
10043d71ae5a4SJacob Faibussowitsch {
10044a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
10045e228b242SToby Isaac   PetscMPIInt result;
10046a68b90caSToby Isaac 
10047a68b90caSToby Isaac   PetscFunctionBegin;
10048a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10049e228b242SToby Isaac   if (anchorSection) {
10050e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
100519566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
100521dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
10053e228b242SToby Isaac   }
10054e228b242SToby Isaac   if (anchorIS) {
10055e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
100569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
100571dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
10058e228b242SToby Isaac   }
10059a68b90caSToby Isaac 
100609566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
100619566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
10062a68b90caSToby Isaac   plex->anchorSection = anchorSection;
10063a68b90caSToby Isaac 
100649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
100659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
10066a68b90caSToby Isaac   plex->anchorIS = anchorIS;
10067a68b90caSToby Isaac 
10068cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
10069a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
10070a68b90caSToby Isaac     const PetscInt *anchors;
10071a68b90caSToby Isaac 
100729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
100739566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
100749566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
10075a68b90caSToby Isaac     for (a = 0; a < size; a++) {
10076a68b90caSToby Isaac       PetscInt p;
10077a68b90caSToby Isaac 
10078a68b90caSToby Isaac       p = anchors[a];
10079a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
10080a68b90caSToby Isaac         PetscInt dof;
10081a68b90caSToby Isaac 
100829566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10083a68b90caSToby Isaac         if (dof) {
100849566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
1008563a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
10086a68b90caSToby Isaac         }
10087a68b90caSToby Isaac       }
10088a68b90caSToby Isaac     }
100899566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
10090a68b90caSToby Isaac   }
10091f7c74593SToby Isaac   /* reset the generic constraints */
100929566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
100933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10094a68b90caSToby Isaac }
10095a68b90caSToby Isaac 
10096d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
10097d71ae5a4SJacob Faibussowitsch {
10098f7c74593SToby Isaac   PetscSection anchorSection;
100996995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
10100a68b90caSToby Isaac 
10101a68b90caSToby Isaac   PetscFunctionBegin;
10102a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
101049566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
101059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
101066995de1eSToby Isaac   if (numFields) {
10107719ab38cSToby Isaac     PetscInt f;
101089566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
10109719ab38cSToby Isaac 
10110719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
10111719ab38cSToby Isaac       PetscInt numComp;
10112719ab38cSToby Isaac 
101139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
101149566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
10115719ab38cSToby Isaac     }
101166995de1eSToby Isaac   }
101179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
101189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
101196995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
101206995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
101216995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
101229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
10123a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
101249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10125a68b90caSToby Isaac     if (dof) {
101269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
101279566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
10128a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
101299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
101309566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
10131a68b90caSToby Isaac       }
10132a68b90caSToby Isaac     }
10133a68b90caSToby Isaac   }
101349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
101359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
101363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10137a68b90caSToby Isaac }
10138a68b90caSToby Isaac 
10139d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
10140d71ae5a4SJacob Faibussowitsch {
10141f7c74593SToby Isaac   PetscSection    aSec;
10142ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
101430ac89760SToby Isaac   const PetscInt *anchors;
101440ac89760SToby Isaac   PetscInt        numFields, f;
1014566ad2231SToby Isaac   IS              aIS;
10146e19f7ee6SMark Adams   MatType         mtype;
10147e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
101480ac89760SToby Isaac 
101490ac89760SToby Isaac   PetscFunctionBegin;
101500ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
101529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
101539566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
101549566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
101559566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
101569566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
101579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
101589566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
10159e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
10160e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
10161e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
101629566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
101639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
101649566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
101656995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
101669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
101679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
101689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
101690ac89760SToby Isaac   i[0] = 0;
101709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
101710ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
10172f19733c5SToby Isaac     PetscInt rDof, rOff, r;
10173f19733c5SToby Isaac 
101749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
10175f19733c5SToby Isaac     if (!rDof) continue;
101769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
101770ac89760SToby Isaac     if (numFields) {
101780ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
101790ac89760SToby Isaac         annz = 0;
10180f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
10181f19733c5SToby Isaac           a = anchors[rOff + r];
10182ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
101839566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
101840ac89760SToby Isaac           annz += aDof;
101850ac89760SToby Isaac         }
101869566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
101879566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
10188ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
101890ac89760SToby Isaac       }
101902f7452b8SBarry Smith     } else {
101910ac89760SToby Isaac       annz = 0;
101929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
101930ac89760SToby Isaac       for (q = 0; q < dof; q++) {
10194ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
10195ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
101969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
101970ac89760SToby Isaac         annz += aDof;
101980ac89760SToby Isaac       }
101999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
102009566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
10201ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
102020ac89760SToby Isaac     }
102030ac89760SToby Isaac   }
102040ac89760SToby Isaac   nnz = i[m];
102059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
102060ac89760SToby Isaac   offset = 0;
102070ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
102080ac89760SToby Isaac     if (numFields) {
102090ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
102109566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
102110ac89760SToby Isaac         for (q = 0; q < dof; q++) {
102120ac89760SToby Isaac           PetscInt rDof, rOff, r;
102139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
102149566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
102150ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
102160ac89760SToby Isaac             PetscInt s;
102170ac89760SToby Isaac 
102180ac89760SToby Isaac             a = anchors[rOff + r];
10219ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
102209566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
102219566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10222ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
102230ac89760SToby Isaac           }
102240ac89760SToby Isaac         }
102250ac89760SToby Isaac       }
102262f7452b8SBarry Smith     } else {
102279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
102280ac89760SToby Isaac       for (q = 0; q < dof; q++) {
102290ac89760SToby Isaac         PetscInt rDof, rOff, r;
102309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
102319566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
102320ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
102330ac89760SToby Isaac           PetscInt s;
102340ac89760SToby Isaac 
102350ac89760SToby Isaac           a = anchors[rOff + r];
10236ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
102379566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
102389566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10239ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
102400ac89760SToby Isaac         }
102410ac89760SToby Isaac       }
102420ac89760SToby Isaac     }
102430ac89760SToby Isaac   }
102449566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
102459566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
102469566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
102479566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
102483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102490ac89760SToby Isaac }
102500ac89760SToby Isaac 
10251d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10252d71ae5a4SJacob Faibussowitsch {
10253f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10254f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1025566ad2231SToby Isaac   Mat          cMat;
1025666ad2231SToby Isaac 
1025766ad2231SToby Isaac   PetscFunctionBegin;
1025866ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1026066ad2231SToby Isaac   if (anchorSection) {
1026144a7f3ddSMatthew G. Knepley     PetscInt Nf;
10262e228b242SToby Isaac 
102639566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
102649566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
102659566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
102669566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
102679566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
102689566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
102699566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
102709566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1027166ad2231SToby Isaac   }
102723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1027366ad2231SToby Isaac }
10274a93c429eSMatthew G. Knepley 
10275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10276d71ae5a4SJacob Faibussowitsch {
10277a93c429eSMatthew G. Knepley   IS           subis;
10278a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10279a93c429eSMatthew G. Knepley 
10280a93c429eSMatthew G. Knepley   PetscFunctionBegin;
102819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1028228b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1028328b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10284a93c429eSMatthew G. Knepley   /* Create subdomain */
102859566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10286a93c429eSMatthew G. Knepley   /* Create submodel */
102879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
102889566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
102899566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
102909566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
102919566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10292a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10293a93c429eSMatthew G. Knepley   if (is) {
10294a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10295a93c429eSMatthew G. Knepley     IS              spIS;
10296a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10297a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10298a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10299a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10300a93c429eSMatthew G. Knepley 
103019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
103029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
103039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
103049566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
103059566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
103069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10307a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10308a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10309a93c429eSMatthew G. Knepley 
103109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10311a93c429eSMatthew G. Knepley       if (gdof > 0) {
10312a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10313a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10314a93c429eSMatthew G. Knepley 
103159566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
103169566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10317a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10318a93c429eSMatthew G. Knepley         }
10319a93c429eSMatthew G. Knepley         subSize += pSubSize;
10320a93c429eSMatthew G. Knepley         if (pSubSize) {
10321a93c429eSMatthew G. Knepley           if (bs < 0) {
10322a93c429eSMatthew G. Knepley             bs = pSubSize;
10323a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10324a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10325a93c429eSMatthew G. Knepley             bs = 1;
10326a93c429eSMatthew G. Knepley           }
10327a93c429eSMatthew G. Knepley         }
10328a93c429eSMatthew G. Knepley       }
10329a93c429eSMatthew G. Knepley     }
10330a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
103319371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
103329371c9d4SSatish Balay     bsLocal[1] = bs;
103339566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
103349371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
103359371c9d4SSatish Balay       bs = 1;
103369371c9d4SSatish Balay     } else {
103379371c9d4SSatish Balay       bs = bsMinMax[0];
103389371c9d4SSatish Balay     }
103399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10340a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10341a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10342a93c429eSMatthew G. Knepley 
103439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10344a93c429eSMatthew G. Knepley       if (gdof > 0) {
10345a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10346a93c429eSMatthew G. Knepley 
103479566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10348a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10349a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10350a93c429eSMatthew G. Knepley 
10351a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10352a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
103539566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
103549566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10355a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10356a93c429eSMatthew G. Knepley           }
103579566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
103589566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10359ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10360a93c429eSMatthew G. Knepley         }
10361a93c429eSMatthew G. Knepley       }
10362a93c429eSMatthew G. Knepley     }
103639566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
103649566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10365a93c429eSMatthew G. Knepley     if (bs > 1) {
10366a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10367a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10368a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10369a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
103709371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
103719371c9d4SSatish Balay             set = 0;
103729371c9d4SSatish Balay             break;
103739371c9d4SSatish Balay           }
10374a93c429eSMatthew G. Knepley         }
10375a93c429eSMatthew G. Knepley       }
103769566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10377a93c429eSMatthew G. Knepley     }
10378a93c429eSMatthew G. Knepley     /* Attach nullspace */
10379a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10380a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10381a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10382a93c429eSMatthew G. Knepley     }
10383a93c429eSMatthew G. Knepley     if (f < Nf) {
10384a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
103859566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
103866823f3c5SBlaise Bourdin 
103879566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
103889566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10389a93c429eSMatthew G. Knepley     }
10390a93c429eSMatthew G. Knepley   }
103913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10392a93c429eSMatthew G. Knepley }
10393c0f0dcc3SMatthew G. Knepley 
10394c0f0dcc3SMatthew G. Knepley /*@
10395c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10396c0f0dcc3SMatthew G. Knepley 
10397a1cb98faSBarry Smith   Input Parameters:
10398a1cb98faSBarry Smith + dm    - The `DM`
10399a1cb98faSBarry Smith - dummy - unused argument
10400a1cb98faSBarry Smith 
10401a1cb98faSBarry Smith   Options Database Key:
10402a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10403c0f0dcc3SMatthew G. Knepley 
10404c0f0dcc3SMatthew G. Knepley   Level: developer
10405c0f0dcc3SMatthew G. Knepley 
104061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10407c0f0dcc3SMatthew G. Knepley @*/
10408d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10409d71ae5a4SJacob Faibussowitsch {
10410b665b14eSToby Isaac   PetscLogHandler default_handler;
10411b665b14eSToby Isaac 
104122611ad71SToby Isaac   PetscFunctionBegin;
104132611ad71SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10414b665b14eSToby Isaac   PetscCall(PetscLogGetDefaultHandler(&default_handler));
10415b665b14eSToby Isaac   if (default_handler) {
10416c0f0dcc3SMatthew G. Knepley     PetscLogEvent      event;
10417c0f0dcc3SMatthew G. Knepley     PetscEventPerfInfo eventInfo;
10418c0f0dcc3SMatthew G. Knepley     PetscReal          cellRate, flopRate;
10419c0f0dcc3SMatthew G. Knepley     PetscInt           cStart, cEnd, Nf, N;
10420c0f0dcc3SMatthew G. Knepley     const char        *name;
10421c0f0dcc3SMatthew G. Knepley 
104229566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
104239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
104249566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
104259566063dSJacob Faibussowitsch     PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
10426b665b14eSToby Isaac     PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo));
10427c0f0dcc3SMatthew G. Knepley     N        = (cEnd - cStart) * Nf * eventInfo.count;
10428c0f0dcc3SMatthew G. Knepley     flopRate = eventInfo.flops / eventInfo.time;
10429c0f0dcc3SMatthew G. Knepley     cellRate = N / eventInfo.time;
1043063a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DM (%s) FE Residual Integration: %" PetscInt_FMT " integrals %d reps\n  Cell rate: %.2g/s flop rate: %.2g MF/s\n", name ? name : "unknown", N, eventInfo.count, (double)cellRate, (double)(flopRate / 1.e6)));
104312611ad71SToby Isaac   } else {
10432b665b14eSToby Isaac     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off or the default log handler is not running. Reconfigure using --with-log and run with -log_view.");
104332611ad71SToby Isaac   }
104343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10435c0f0dcc3SMatthew G. Knepley }
10436