xref: /petsc/src/dm/impls/plex/plex.c (revision 30cbcd5d28835bf13680f6b77f3410cc4cf99a18)
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) {
96c306944fSJed 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     }
104c306944fSJed 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   /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */
1319c600e38SMatt McGurn   PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1));
1329c600e38SMatt McGurn   PetscCall(DMGetCoordinateDim(dm, &cdim));
1339c600e38SMatt McGurn   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1349c600e38SMatt McGurn   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1359c600e38SMatt McGurn   if (field >= 0) {
1369c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES]));
1379c600e38SMatt McGurn   } else {
1389c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES]));
1399c600e38SMatt McGurn   }
1409c600e38SMatt McGurn 
1419c600e38SMatt McGurn   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
1429c600e38SMatt McGurn   PetscCall(DMPlexGetDepth(dm, &depth));
1439c600e38SMatt McGurn   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
1449c600e38SMatt McGurn   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
1459c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1469c600e38SMatt McGurn     const DMPolytopeType ict = (DMPolytopeType)c;
1479c600e38SMatt McGurn     PetscInt             dep;
1489c600e38SMatt McGurn 
1499c600e38SMatt McGurn     if (ict == DM_POLYTOPE_FV_GHOST) continue;
1509c600e38SMatt McGurn     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1519c600e38SMatt McGurn     if (pStart >= 0) {
1529c600e38SMatt McGurn       PetscCall(DMLabelGetValue(depthLabel, cStart, &dep));
1539c600e38SMatt McGurn       if (dep != depth - cellHeight) continue;
1549c600e38SMatt McGurn     }
1559c600e38SMatt McGurn     if (field >= 0) {
1569c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c]));
1579c600e38SMatt McGurn     } else {
1589c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c]));
1599c600e38SMatt McGurn     }
1609c600e38SMatt McGurn   }
1619c600e38SMatt McGurn 
1629c600e38SMatt McGurn   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1639c600e38SMatt McGurn   *types = 0;
1649c600e38SMatt McGurn 
1659c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) {
1669c600e38SMatt McGurn     if (globalvcdof[c]) ++(*types);
1679c600e38SMatt McGurn   }
1689c600e38SMatt McGurn 
1699c600e38SMatt McGurn   PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft));
1709c600e38SMatt McGurn   t = 0;
1719c600e38SMatt McGurn   if (globalvcdof[DM_NUM_POLYTOPES]) {
1729c600e38SMatt McGurn     sStart[t] = vStart;
1739c600e38SMatt McGurn     sEnd[t]   = vEnd;
1749c600e38SMatt McGurn     ft[t]     = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
1759c600e38SMatt McGurn     ++t;
1769c600e38SMatt McGurn   }
1779c600e38SMatt McGurn 
1789c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1799c600e38SMatt McGurn     if (globalvcdof[c]) {
1809c600e38SMatt McGurn       const DMPolytopeType ict = (DMPolytopeType)c;
1819c600e38SMatt McGurn 
1829c600e38SMatt McGurn       PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1839c600e38SMatt McGurn       sStart[t] = cStart;
1849c600e38SMatt McGurn       sEnd[t]   = cEnd;
1859c600e38SMatt McGurn       ft[t]     = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD;
1869c600e38SMatt McGurn       ++t;
1879c600e38SMatt McGurn     }
1889c600e38SMatt McGurn   }
1899c600e38SMatt McGurn 
1904ad8454bSPierre Jolivet   if (!*types) {
1919c600e38SMatt McGurn     if (field >= 0) {
1929c600e38SMatt McGurn       const char *fieldname;
1939c600e38SMatt McGurn 
1949c600e38SMatt McGurn       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
1959c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
1969c600e38SMatt McGurn     } else {
1979c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
1989c600e38SMatt McGurn     }
1999c600e38SMatt McGurn   }
2009c600e38SMatt McGurn 
2019c600e38SMatt McGurn   *ssStart = sStart;
2029c600e38SMatt McGurn   *ssEnd   = sEnd;
2039c600e38SMatt McGurn   *sft     = ft;
2049c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2059c600e38SMatt McGurn }
2069c600e38SMatt McGurn 
2079c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft)
2089c600e38SMatt McGurn {
2099c600e38SMatt McGurn   PetscFunctionBegin;
2109c600e38SMatt McGurn   PetscCall(PetscFree3(*sStart, *sEnd, *ft));
2119c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2129c600e38SMatt McGurn }
2139c600e38SMatt McGurn 
214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
215d71ae5a4SJacob Faibussowitsch {
216412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
217a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
2187e42fee7SMatthew G. Knepley 
2197e42fee7SMatthew G. Knepley   PetscFunctionBegin;
220e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
2219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
2229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
2249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
2257e42fee7SMatthew G. Knepley   if (field >= 0) {
2269566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
2279566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
2287e42fee7SMatthew G. Knepley   } else {
2299566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
2309566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
2317e42fee7SMatthew G. Knepley   }
232712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
233a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
2347e42fee7SMatthew G. Knepley     *sStart = vStart;
2357e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
236f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
2377e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
238a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
2397e42fee7SMatthew G. Knepley     *sStart = cStart;
2407e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
241f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
2427e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
243e630c359SToby Isaac   } else {
244e630c359SToby Isaac     if (field >= 0) {
245e630c359SToby Isaac       const char *fieldname;
246e630c359SToby Isaac 
2479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
24863a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
249e630c359SToby Isaac     } else {
25063a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
251e630c359SToby Isaac     }
252e630c359SToby Isaac   }
2533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2547e42fee7SMatthew G. Knepley }
2557e42fee7SMatthew G. Knepley 
2566913077dSMatthew G. Knepley /*@
2576913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
2586913077dSMatthew G. Knepley 
25920f4b53cSBarry Smith   Collective
2606913077dSMatthew G. Knepley 
2616913077dSMatthew G. Knepley   Input Parameters:
262a1cb98faSBarry Smith + dm     - The `DMPLEX` object
2636913077dSMatthew G. Knepley . n      - The number of vectors
2646913077dSMatthew G. Knepley . u      - The array of local vectors
265a1cb98faSBarry Smith - viewer - The `PetscViewer`
2666913077dSMatthew G. Knepley 
2676913077dSMatthew G. Knepley   Level: advanced
2686913077dSMatthew G. Knepley 
2691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
2706913077dSMatthew G. Knepley @*/
271d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
272d71ae5a4SJacob Faibussowitsch {
2736913077dSMatthew G. Knepley   PetscDS            ds;
2746913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
2756913077dSMatthew G. Knepley   PetscDrawLG        lg;
2766913077dSMatthew G. Knepley   Vec                coordinates;
2776913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
2786913077dSMatthew G. Knepley   PetscReal         *vals;
2796913077dSMatthew G. Knepley   PetscInt          *Nc;
2806913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
2816913077dSMatthew G. Knepley   char             **names;
2826913077dSMatthew G. Knepley 
2836913077dSMatthew G. Knepley   PetscFunctionBegin;
2849566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
2859566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2869566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
2879566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2886913077dSMatthew G. Knepley 
2899566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2903ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
2919566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
2926913077dSMatthew G. Knepley 
2939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
2946913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
2956913077dSMatthew G. Knepley     const char *vname;
2966913077dSMatthew G. Knepley 
2979566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
2986913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
2996913077dSMatthew G. Knepley       PetscObject disc;
3006913077dSMatthew G. Knepley       const char *fname;
3016913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
3026913077dSMatthew G. Knepley 
3039566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
3046913077dSMatthew G. Knepley       /* TODO Create names for components */
3056913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
3069566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
307c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
308c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
309c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
3109566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
3116913077dSMatthew G. Knepley       }
3126913077dSMatthew G. Knepley     }
3136913077dSMatthew G. Knepley   }
3149566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
3156913077dSMatthew G. Knepley   /* Just add P_1 support for now */
3169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3179566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3189566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
3199566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
3206913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
3216913077dSMatthew G. Knepley     PetscScalar *x, *svals;
3226913077dSMatthew G. Knepley 
3239566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
3246913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
3259566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
3266913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
3276913077dSMatthew G. Knepley     }
3289566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
3296913077dSMatthew G. Knepley   }
3309566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
3319566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
3329566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
3339566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
3346913077dSMatthew G. Knepley 
3359566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
3369566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
3373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3386913077dSMatthew G. Knepley }
3396913077dSMatthew G. Knepley 
340d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
341d71ae5a4SJacob Faibussowitsch {
3426913077dSMatthew G. Knepley   DM dm;
3436913077dSMatthew G. Knepley 
3446913077dSMatthew G. Knepley   PetscFunctionBegin;
3459566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
3469566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
3473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3486913077dSMatthew G. Knepley }
3496913077dSMatthew G. Knepley 
350d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
351d71ae5a4SJacob Faibussowitsch {
352e412dcbdSMatthew G. Knepley   DM                 dm;
353d1df6f1dSMatthew G. Knepley   PetscSection       s;
354e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
355e412dcbdSMatthew G. Knepley   DM                 cdm;
356e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
357e412dcbdSMatthew G. Knepley   Vec                coordinates;
358c9c77995SMatthew G. Knepley   const PetscScalar *array;
359c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
360339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
3616913077dSMatthew G. Knepley   PetscBool          flg;
362d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
363e412dcbdSMatthew G. Knepley   const char        *name;
364339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
365e412dcbdSMatthew G. Knepley 
366e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
3679566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3689566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3709566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
3719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
3729566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
3739566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
3749566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
3759566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
378e412dcbdSMatthew G. Knepley 
3799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
3809566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
381e412dcbdSMatthew G. Knepley 
3829566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
383c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
3849566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
385e412dcbdSMatthew G. Knepley 
386d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
387d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
388d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
389d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
390d1df6f1dSMatthew G. Knepley     IS          fis;
391d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
392d1df6f1dSMatthew G. Knepley     const char *fname;
393d1df6f1dSMatthew G. Knepley 
3949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
3959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
396d1df6f1dSMatthew G. Knepley 
3979566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
398ad540459SPierre Jolivet     else prefix[0] = '\0';
399d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4009566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
4019566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
4029566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
4039566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
404d1df6f1dSMatthew G. Knepley     }
405d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
406d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
407d1df6f1dSMatthew G. Knepley 
4089566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
40963a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
41063a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
4119566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
412d1df6f1dSMatthew G. Knepley 
413d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
4149566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
415339e3443SMatthew G. Knepley       if (!flg) {
4169566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
4179566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
418d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
419339e3443SMatthew G. Knepley       }
420c9c77995SMatthew G. Knepley 
4219566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
4229566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
423c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
4249566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
425e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
42699a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
427c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
428c9c77995SMatthew G. Knepley         PetscBool          isDG;
429e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
430e412dcbdSMatthew G. Knepley 
4319566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
432339e3443SMatthew G. Knepley         if (a) {
433d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
434339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
435339e3443SMatthew G. Knepley         } else {
436339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
437339e3443SMatthew G. Knepley           PetscInt     numVals, va;
438339e3443SMatthew G. Knepley 
4399566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
44063a3b9bcSJacob 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);
441d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
442d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
443d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
444d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
445339e3443SMatthew G. Knepley             break;
446d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
447d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
448d1df6f1dSMatthew 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]);
449d1df6f1dSMatthew G. Knepley             break;
450d71ae5a4SJacob Faibussowitsch           default:
451d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
452339e3443SMatthew G. Knepley           }
4539566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
454339e3443SMatthew G. Knepley         }
455c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
456e412dcbdSMatthew G. Knepley         switch (numCoords) {
457e412dcbdSMatthew G. Knepley         case 6:
4589edc3542SMatthew Knepley         case 12: /* Localized triangle */
4599566063dSJacob 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]));
460e412dcbdSMatthew G. Knepley           break;
461e412dcbdSMatthew G. Knepley         case 8:
4629edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
4639566063dSJacob 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]));
4649566063dSJacob 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]));
465e412dcbdSMatthew G. Knepley           break;
466d71ae5a4SJacob Faibussowitsch         default:
467d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
468e412dcbdSMatthew G. Knepley         }
469c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
470e412dcbdSMatthew G. Knepley       }
4719566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
4729566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
4739566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
4749566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
475d1df6f1dSMatthew G. Knepley     }
476d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4779566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
4789566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
4799566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
480d1df6f1dSMatthew G. Knepley     }
481d1df6f1dSMatthew G. Knepley   }
4823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
483e412dcbdSMatthew G. Knepley }
484e412dcbdSMatthew G. Knepley 
485d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
486d71ae5a4SJacob Faibussowitsch {
4876913077dSMatthew G. Knepley   DM        dm;
4886913077dSMatthew G. Knepley   PetscDraw draw;
4896913077dSMatthew G. Knepley   PetscInt  dim;
4906913077dSMatthew G. Knepley   PetscBool isnull;
4916913077dSMatthew G. Knepley 
4926913077dSMatthew G. Knepley   PetscFunctionBegin;
4939566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4949566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4953ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
4966913077dSMatthew G. Knepley 
4979566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4989566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
4996913077dSMatthew G. Knepley   switch (dim) {
500d71ae5a4SJacob Faibussowitsch   case 1:
501d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
502d71ae5a4SJacob Faibussowitsch     break;
503d71ae5a4SJacob Faibussowitsch   case 2:
504d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
505d71ae5a4SJacob Faibussowitsch     break;
506d71ae5a4SJacob Faibussowitsch   default:
507d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
5086913077dSMatthew G. Knepley   }
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5106913077dSMatthew G. Knepley }
5116913077dSMatthew G. Knepley 
512d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
513d71ae5a4SJacob Faibussowitsch {
514684b87d9SLisandro Dalcin   DM                      dm;
515684b87d9SLisandro Dalcin   Vec                     locv;
516684b87d9SLisandro Dalcin   const char             *name;
517684b87d9SLisandro Dalcin   PetscSection            section;
518684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
519e630c359SToby Isaac   PetscInt                numFields;
520684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
521684b87d9SLisandro Dalcin 
522684b87d9SLisandro Dalcin   PetscFunctionBegin;
5239566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
5249566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
5259566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
5269566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
5279566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
5289566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
5299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
530e630c359SToby Isaac   if (!numFields) {
5319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
5329566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
533e630c359SToby Isaac   } else {
534e630c359SToby Isaac     PetscInt f;
535e630c359SToby Isaac 
536e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
5379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
538e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
5399566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
5409566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
541e630c359SToby Isaac     }
5429566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
543e630c359SToby Isaac   }
5443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545684b87d9SLisandro Dalcin }
546684b87d9SLisandro Dalcin 
547d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
548d71ae5a4SJacob Faibussowitsch {
549552f7358SJed Brown   DM        dm;
5505f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
551552f7358SJed Brown 
552552f7358SJed Brown   PetscFunctionBegin;
5539566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
55428b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5595f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5605f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
561684b87d9SLisandro Dalcin     PetscInt    i, numFields;
562684b87d9SLisandro Dalcin     PetscObject fe;
563ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
564684b87d9SLisandro Dalcin     Vec         locv = v;
565684b87d9SLisandro Dalcin     const char *name;
566684b87d9SLisandro Dalcin     PetscInt    step;
567684b87d9SLisandro Dalcin     PetscReal   time;
568ef31f671SMatthew G. Knepley 
5699566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
570684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
5719566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
5729371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
5739371c9d4SSatish Balay         fem = PETSC_TRUE;
5749371c9d4SSatish Balay         break;
5759371c9d4SSatish Balay       }
576ef31f671SMatthew G. Knepley     }
577684b87d9SLisandro Dalcin     if (fem) {
578798534f6SMatthew G. Knepley       PetscObject isZero;
579798534f6SMatthew G. Knepley 
5809566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
5819566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
5829566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
5839566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5849566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5859566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
5869566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
5879566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
588ef31f671SMatthew G. Knepley     }
589552f7358SJed Brown     if (isvtk) {
5909566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
591b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
592b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5939566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
594b136c2c9SMatthew G. Knepley #else
595b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
596b136c2c9SMatthew G. Knepley #endif
597f13a32a3SMatthew G. Knepley     } else if (isdraw) {
5989566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
599684b87d9SLisandro Dalcin     } else if (isglvis) {
6009566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
6019566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
6029566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
6035f34f2dcSJed Brown     } else if (iscgns) {
6045f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
6055f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
6065f34f2dcSJed Brown #else
6075f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
6085f34f2dcSJed Brown #endif
609684b87d9SLisandro Dalcin     }
610798534f6SMatthew G. Knepley     if (fem) {
6119566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6129566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
613798534f6SMatthew G. Knepley     }
614552f7358SJed Brown   } else {
615684b87d9SLisandro Dalcin     PetscBool isseq;
616684b87d9SLisandro Dalcin 
6179566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6189566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6199566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
620552f7358SJed Brown   }
6213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
622552f7358SJed Brown }
623552f7358SJed Brown 
624d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
625d71ae5a4SJacob Faibussowitsch {
626552f7358SJed Brown   DM        dm;
6275f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
628552f7358SJed Brown 
629552f7358SJed Brown   PetscFunctionBegin;
6309566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
6339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
6365f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
6379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6385f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
639552f7358SJed Brown     Vec         locv;
640798534f6SMatthew G. Knepley     PetscObject isZero;
641552f7358SJed Brown     const char *name;
642552f7358SJed Brown 
6439566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
6449566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6459566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
6469566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6479566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6489566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6499566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6509566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
6519566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6529566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
653b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
654b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6559566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
656b136c2c9SMatthew G. Knepley #else
657b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
658b136c2c9SMatthew G. Knepley #endif
6596823f3c5SBlaise Bourdin   } else if (isexodusii) {
6606823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6619566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
6626823f3c5SBlaise Bourdin #else
6636823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6646823f3c5SBlaise Bourdin #endif
665552f7358SJed Brown   } else {
666684b87d9SLisandro Dalcin     PetscBool isseq;
667684b87d9SLisandro Dalcin 
6689566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6699566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6709566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
671552f7358SJed Brown   }
6723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
673552f7358SJed Brown }
674552f7358SJed Brown 
675d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
676d71ae5a4SJacob Faibussowitsch {
677d930f514SMatthew G. Knepley   DM                dm;
678d930f514SMatthew G. Knepley   MPI_Comm          comm;
679d930f514SMatthew G. Knepley   PetscViewerFormat format;
680d930f514SMatthew G. Knepley   Vec               v;
681d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
682d930f514SMatthew G. Knepley 
683d930f514SMatthew G. Knepley   PetscFunctionBegin;
6849566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
6859566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
68628b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6879566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
690d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
691a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
692a8ad634aSStefano Zampini     /* this need a better fix */
693a8ad634aSStefano Zampini     if (dm->useNatural) {
694a8ad634aSStefano Zampini       if (dm->sfNatural) {
695d930f514SMatthew G. Knepley         const char *vecname;
696d930f514SMatthew G. Knepley         PetscInt    n, nroots;
697d930f514SMatthew G. Knepley 
6989566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
6999566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
700d930f514SMatthew G. Knepley         if (n == nroots) {
701f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
7029566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
7039566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
7049566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7059566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
706d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
707d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
708a8ad634aSStefano Zampini     } else v = originalv;
709a8ad634aSStefano Zampini   } else v = originalv;
710a8ad634aSStefano Zampini 
711d930f514SMatthew G. Knepley   if (ishdf5) {
712d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7139566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
714d930f514SMatthew G. Knepley #else
715d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
716d930f514SMatthew G. Knepley #endif
717d930f514SMatthew G. Knepley   } else if (isvtk) {
718d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
719d930f514SMatthew G. Knepley   } else {
720d930f514SMatthew G. Knepley     PetscBool isseq;
721d930f514SMatthew G. Knepley 
7229566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7239566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
7249566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
725d930f514SMatthew G. Knepley   }
726f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
728d930f514SMatthew G. Knepley }
729d930f514SMatthew G. Knepley 
730d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
731d71ae5a4SJacob Faibussowitsch {
7322c40f234SMatthew G. Knepley   DM        dm;
7332c40f234SMatthew G. Knepley   PetscBool ishdf5;
7342c40f234SMatthew G. Knepley 
7352c40f234SMatthew G. Knepley   PetscFunctionBegin;
7369566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
73728b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7392c40f234SMatthew G. Knepley   if (ishdf5) {
7402c40f234SMatthew G. Knepley     DM          dmBC;
7412c40f234SMatthew G. Knepley     Vec         gv;
7422c40f234SMatthew G. Knepley     const char *name;
7432c40f234SMatthew G. Knepley 
7449566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
7459566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
7469566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
7479566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
7489566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
7499566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
7509566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
7519566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
7521baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7542c40f234SMatthew G. Knepley }
7552c40f234SMatthew G. Knepley 
756d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
757d71ae5a4SJacob Faibussowitsch {
7582c40f234SMatthew G. Knepley   DM        dm;
7596823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
7602c40f234SMatthew G. Knepley 
7612c40f234SMatthew G. Knepley   PetscFunctionBegin;
7629566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
76328b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
7662c40f234SMatthew G. Knepley   if (ishdf5) {
767878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7689566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
769b136c2c9SMatthew G. Knepley #else
770b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
771878b459fSMatthew G. Knepley #endif
7726823f3c5SBlaise Bourdin   } else if (isexodusii) {
7736823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
7749566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
7756823f3c5SBlaise Bourdin #else
7766823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
7776823f3c5SBlaise Bourdin #endif
7781baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
780552f7358SJed Brown }
781552f7358SJed Brown 
782d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
783d71ae5a4SJacob Faibussowitsch {
784d930f514SMatthew G. Knepley   DM                dm;
785d930f514SMatthew G. Knepley   PetscViewerFormat format;
786d930f514SMatthew G. Knepley   PetscBool         ishdf5;
787d930f514SMatthew G. Knepley 
788d930f514SMatthew G. Knepley   PetscFunctionBegin;
7899566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
79028b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7919566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
793d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
794a8ad634aSStefano Zampini     if (dm->useNatural) {
795d930f514SMatthew G. Knepley       if (dm->sfNatural) {
796d930f514SMatthew G. Knepley         if (ishdf5) {
797d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
798d930f514SMatthew G. Knepley           Vec         v;
799d930f514SMatthew G. Knepley           const char *vecname;
800d930f514SMatthew G. Knepley 
801f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
8029566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
8039566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
8049566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
8059566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
8069566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
807f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
808d930f514SMatthew G. Knepley #else
809d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
810d930f514SMatthew G. Knepley #endif
811d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
812d930f514SMatthew G. Knepley       }
8131baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
814d930f514SMatthew G. Knepley   }
8153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
816d930f514SMatthew G. Knepley }
817d930f514SMatthew G. Knepley 
818d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
819d71ae5a4SJacob Faibussowitsch {
820731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
821731e8ddeSMatthew G. Knepley   Vec                coordinates;
822ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
823731e8ddeSMatthew G. Knepley   const char        *name[4];
824731e8ddeSMatthew G. Knepley   const PetscScalar *a;
825731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
826731e8ddeSMatthew G. Knepley 
827731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
8289566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8299566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
8329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
8339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8359566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
836731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
837731e8ddeSMatthew G. Knepley   name[1]       = "edge";
838731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
839731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
840731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
841731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
842ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
843731e8ddeSMatthew G. Knepley 
8449566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
84563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
8469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
848731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
849731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
850731e8ddeSMatthew G. Knepley 
851731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
8529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
853731e8ddeSMatthew G. Knepley       if (!dof) continue;
8549566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
8559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
85663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
857731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
8589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
859731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
8609566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
8619566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
862731e8ddeSMatthew G. Knepley         }
8639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
864731e8ddeSMatthew G. Knepley       }
8659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
866731e8ddeSMatthew G. Knepley     }
8679566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
869731e8ddeSMatthew G. Knepley   }
8709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
8713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
872731e8ddeSMatthew G. Knepley }
873731e8ddeSMatthew G. Knepley 
8749371c9d4SSatish Balay typedef enum {
8759371c9d4SSatish Balay   CS_CARTESIAN,
8769371c9d4SSatish Balay   CS_POLAR,
8779371c9d4SSatish Balay   CS_CYLINDRICAL,
8789371c9d4SSatish Balay   CS_SPHERICAL
8799371c9d4SSatish Balay } CoordSystem;
88019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
88119ad8254SMatthew G. Knepley 
882d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
883d71ae5a4SJacob Faibussowitsch {
88419ad8254SMatthew G. Knepley   PetscInt i;
88519ad8254SMatthew G. Knepley 
88619ad8254SMatthew G. Knepley   PetscFunctionBegin;
88719ad8254SMatthew G. Knepley   if (dim > 3) {
8889566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
88919ad8254SMatthew G. Knepley   } else {
890bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
89119ad8254SMatthew G. Knepley 
89219ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
89319ad8254SMatthew G. Knepley     switch (cs) {
8949371c9d4SSatish Balay     case CS_CARTESIAN:
8959371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
8969371c9d4SSatish Balay       break;
89719ad8254SMatthew G. Knepley     case CS_POLAR:
89863a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
89919ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90019ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90119ad8254SMatthew G. Knepley       break;
90219ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
90363a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
90419ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90519ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90619ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
90719ad8254SMatthew G. Knepley       break;
90819ad8254SMatthew G. Knepley     case CS_SPHERICAL:
90963a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
91019ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
91119ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
91219ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
91319ad8254SMatthew G. Knepley       break;
91419ad8254SMatthew G. Knepley     }
9159566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
91619ad8254SMatthew G. Knepley   }
9173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91819ad8254SMatthew G. Knepley }
91919ad8254SMatthew G. Knepley 
920d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
921d71ae5a4SJacob Faibussowitsch {
922552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
9236858538eSMatthew G. Knepley   DM                cdm, cdmCell;
9246858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
9256858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
926552f7358SJed Brown   PetscViewerFormat format;
927552f7358SJed Brown 
928552f7358SJed Brown   PetscFunctionBegin;
9299566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
930552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
931552f7358SJed Brown     const char *name;
932f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
9339318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
934552f7358SJed Brown     PetscMPIInt rank, size;
935552f7358SJed Brown 
9369f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9379f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9389f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9399f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9409f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9419f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9449566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
9459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
9479566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94963a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
95063a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
95163a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
95263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
9539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
95463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
955552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
956552f7358SJed Brown       PetscInt dof, off, s;
957552f7358SJed Brown 
9589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
9599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
96048a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
961552f7358SJed Brown     }
9629566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
96363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
96463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
965552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
966552f7358SJed Brown       PetscInt dof, off, c;
967552f7358SJed Brown 
9689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
9699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
97048a46eb9SPierre 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]));
971552f7358SJed Brown     }
9729566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
9739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9743d2e540fSStefano Zampini     if (coordSection && coordinates) {
97519ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
9766858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
9776858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
97819ad8254SMatthew G. Knepley       PetscMPIInt        rank;
97919ad8254SMatthew G. Knepley       const char        *name;
98019ad8254SMatthew G. Knepley 
9819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
9829566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
9839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
98463a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
9859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
9866858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
9876858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
9886858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
9896858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
9909566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
99163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
99263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
9939566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
99419ad8254SMatthew G. Knepley 
9959566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
9966858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
9979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
9989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
99919ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
100019ad8254SMatthew G. Knepley         PetscInt dof, off;
100119ad8254SMatthew G. Knepley 
10026858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
10039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
10049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
10056858538eSMatthew G. Knepley           if (dof) {
100663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10079566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
10089566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
100919ad8254SMatthew G. Knepley           }
10106858538eSMatthew G. Knepley         }
10116858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
10126858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
10136858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
10146858538eSMatthew G. Knepley           if (dof) {
10156858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10166858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
10176858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
10186858538eSMatthew G. Knepley           }
10196858538eSMatthew G. Knepley         }
10206858538eSMatthew G. Knepley       }
10219566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
10239566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
10246858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
10253d2e540fSStefano Zampini     }
10269566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10279566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
10289318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
10299318fe57SMatthew G. Knepley       DMLabel     label;
10309318fe57SMatthew G. Knepley       PetscBool   isdepth;
10319318fe57SMatthew G. Knepley       const char *name;
10329318fe57SMatthew G. Knepley 
10339566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
10349566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
10359318fe57SMatthew G. Knepley       if (isdepth) continue;
10369566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
10379566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
10389318fe57SMatthew G. Knepley     }
1039552f7358SJed Brown     if (size > 1) {
1040552f7358SJed Brown       PetscSF sf;
1041552f7358SJed Brown 
10429566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
10439566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
1044552f7358SJed Brown     }
10454e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
10469566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1047552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
10480588280cSMatthew G. Knepley     const char  *name, *color;
10490588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
10500588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
1051fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
1052552f7358SJed Brown     PetscReal    scale      = 2.0;
105378081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
1054b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
10550588280cSMatthew G. Knepley     double       tcoords[3];
1056552f7358SJed Brown     PetscScalar *coords;
1057b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
1058552f7358SJed Brown     PetscMPIInt  rank, size;
10590588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
1060b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
1061fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
1062fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
1063552f7358SJed Brown 
10649f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
10659f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
10669f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10679f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
10689f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
10699f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
10709566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
10719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
10729566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10730588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
10740588280cSMatthew G. Knepley     numColors  = 10;
10750588280cSMatthew G. Knepley     numLColors = 10;
10769566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
10779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
10789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
10799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
1080b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
1081b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
1082b7f6ffafSMatthew G. Knepley     n = 4;
10839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
10841dca8a05SBarry 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);
1085bd3611e6SMatthew G. Knepley     n = 4;
10869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
10871dca8a05SBarry 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);
10889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
10890588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
10909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
10910588280cSMatthew G. Knepley     if (!useColors) {
10920588280cSMatthew G. Knepley       numColors = 3;
10939566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
10940588280cSMatthew G. Knepley     }
10959566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
10960588280cSMatthew G. Knepley     if (!useColors) {
10970588280cSMatthew G. Knepley       numLColors = 4;
10989566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
10990588280cSMatthew G. Knepley     }
11009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
1101b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
11029566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
11031dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1104202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
11059566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1106fe1cc32dSStefano Zampini 
1107fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
11089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
11099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
11109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
11119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1112fe1cc32dSStefano Zampini     if (lflg) {
1113fe1cc32dSStefano Zampini       DMLabel lbl;
1114fe1cc32dSStefano Zampini 
11159566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1116fe1cc32dSStefano Zampini       if (lbl) {
1117fe1cc32dSStefano Zampini         PetscInt val, defval;
1118fe1cc32dSStefano Zampini 
11199566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
11209566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1121fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1122fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1123fe1cc32dSStefano Zampini           PetscInt  closureSize;
1124fe1cc32dSStefano Zampini 
11259566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1126fe1cc32dSStefano Zampini           if (val == defval) continue;
1127fe1cc32dSStefano Zampini 
11289566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
112948a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
11309566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1131fe1cc32dSStefano Zampini         }
1132fe1cc32dSStefano Zampini       }
1133fe1cc32dSStefano Zampini     }
1134fe1cc32dSStefano Zampini 
11359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
11369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
11379566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
11389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
11390588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1140552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1141552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1142552f7358SJed Brown \\usetikzlibrary{arrows}\n\
11435f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
11440588280cSMatthew G. Knepley     if (size > 1) {
11459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1146770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
114763a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
114863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1149770b213bSMatthew G Knepley       }
11509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
11510588280cSMatthew G. Knepley     }
1152b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1153b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1154b7f6ffafSMatthew G. Knepley 
115563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
115663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
115763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
11589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
115963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
116063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
11619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
116263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
116363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
116463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
116563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
11669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1167b7f6ffafSMatthew G. Knepley     }
11689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1169fe1cc32dSStefano Zampini 
1170552f7358SJed Brown     /* Plot vertices */
11719566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
11729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1173552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1174552f7358SJed Brown       PetscInt  off, dof, d;
11750588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1176552f7358SJed Brown 
1177fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
11789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
11799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
11809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
118163a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
11820588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11830588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1184c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
11850588280cSMatthew G. Knepley       }
11860588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
11879371c9d4SSatish Balay       if (dim == 3) {
11889371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
11899371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
11909371c9d4SSatish Balay         tcoords[2]    = -tmp;
11919371c9d4SSatish Balay       }
1192552f7358SJed Brown       for (d = 0; d < dof; ++d) {
11939566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11949566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1195552f7358SJed Brown       }
1196b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1197b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
11980588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
11990588280cSMatthew G. Knepley         PetscInt val;
12009566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
12019371c9d4SSatish Balay         if (val >= 0) {
12029371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12039371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12049371c9d4SSatish Balay           break;
12059371c9d4SSatish Balay         }
12060588280cSMatthew G. Knepley       }
1207b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
120863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1209b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
121063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
12111baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1212552f7358SJed Brown     }
12139566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12149566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1215b7f6ffafSMatthew G. Knepley     /* Plot edges */
1216b7f6ffafSMatthew G. Knepley     if (plotEdges) {
12179566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
12189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1219b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1220b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1221b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1222b7f6ffafSMatthew G. Knepley 
1223b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
12249566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
122563a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
12269566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
12279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
12289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
12299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
12309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1231b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1232b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1233b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1234b7f6ffafSMatthew G. Knepley         }
1235b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12369371c9d4SSatish Balay         if (dim == 3) {
12379371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12389371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12399371c9d4SSatish Balay           tcoords[2]    = -tmp;
12409371c9d4SSatish Balay         }
1241b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12429566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12439566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1244b7f6ffafSMatthew G. Knepley         }
1245b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1246b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1247b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1248b7f6ffafSMatthew G. Knepley           PetscInt val;
1249bd3611e6SMatthew G. Knepley           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12509371c9d4SSatish Balay           if (val >= 0) {
12519371c9d4SSatish Balay             color = lcolors[l % numLColors];
12529371c9d4SSatish Balay             break;
12539371c9d4SSatish Balay           }
1254b7f6ffafSMatthew G. Knepley         }
125563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1256b7f6ffafSMatthew G. Knepley       }
12579566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
12589566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
12599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1260b7f6ffafSMatthew G. Knepley     }
1261846a3e8bSMatthew G. Knepley     /* Plot cells */
1262b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1263846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1264846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1265846a3e8bSMatthew G. Knepley 
1266fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1267846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1268846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1269846a3e8bSMatthew G. Knepley           PetscInt val;
12709566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12719371c9d4SSatish Balay           if (val >= 0) {
12729371c9d4SSatish Balay             color = lcolors[l % numLColors];
12739371c9d4SSatish Balay             break;
12749371c9d4SSatish Balay           }
1275846a3e8bSMatthew G. Knepley         }
12769566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
127763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1278846a3e8bSMatthew G. Knepley       }
1279846a3e8bSMatthew G. Knepley     } else {
1280b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1281846a3e8bSMatthew G. Knepley 
1282b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1283b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1284fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
12859566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1286c306944fSJed Brown         if (DMPolytopeTypeIsHybrid(ct)) {
1287b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1288b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1289b7f6ffafSMatthew G. Knepley 
12909566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
12919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1292b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1293b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1294b7f6ffafSMatthew G. Knepley 
12959566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
129663a3b9bcSJacob 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));
1297b7f6ffafSMatthew G. Knepley           }
1298b7f6ffafSMatthew G. Knepley         } else {
1299b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1300b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1301b7f6ffafSMatthew G. Knepley 
13029566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1303846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1304846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1305846a3e8bSMatthew G. Knepley 
1306b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1307846a3e8bSMatthew G. Knepley           }
13089566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1309b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1310b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1311b7f6ffafSMatthew G. Knepley 
1312b7f6ffafSMatthew G. Knepley             if (v > 0) {
1313b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1314b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1315b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1316b7f6ffafSMatthew G. Knepley 
13179371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
13189371c9d4SSatish Balay                 endpoints[1] = vertex;
13199566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
132063a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
132163a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
13229566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
13231baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1324b7f6ffafSMatthew G. Knepley             }
132563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1326b7f6ffafSMatthew G. Knepley           }
13279566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
13289566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1329846a3e8bSMatthew G. Knepley         }
1330846a3e8bSMatthew G. Knepley       }
1331b7f6ffafSMatthew G. Knepley     }
1332846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1333846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1334846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1335c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1336c713ec31SMatthew G. Knepley       const PetscScalar *array;
1337c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1338c713ec31SMatthew G. Knepley       PetscBool          isDG;
1339846a3e8bSMatthew G. Knepley 
1340fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1341c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1342c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1343c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
13449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1345c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1346c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1347c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1348846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1349846a3e8bSMatthew G. Knepley         }
1350846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
13519371c9d4SSatish Balay         if (cdim == 3) {
13529371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
13539371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
13549371c9d4SSatish Balay           tcoords[2]    = -tmp;
13559371c9d4SSatish Balay         }
1356ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1357846a3e8bSMatthew G. Knepley       }
1358ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1359c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1360c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
13619566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
13629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1363846a3e8bSMatthew G. Knepley       }
1364b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1365b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1366846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1367846a3e8bSMatthew G. Knepley         PetscInt val;
13689566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
13699371c9d4SSatish Balay         if (val >= 0) {
13709371c9d4SSatish Balay           color     = lcolors[l % numLColors];
13719371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
13729371c9d4SSatish Balay           break;
13739371c9d4SSatish Balay         }
1374846a3e8bSMatthew G. Knepley       }
1375b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
137663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1377b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
137863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
13791baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1380846a3e8bSMatthew G. Knepley     }
1381b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1382b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
13839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
13849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
13859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
13879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1388552f7358SJed Brown 
1389b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
13909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
13919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
13929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
13949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1395b7f6ffafSMatthew G. Knepley 
1396b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
13979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
13989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
13999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
14009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
14019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1402b7f6ffafSMatthew G. Knepley 
1403b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1404b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1405b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1406b7f6ffafSMatthew G. Knepley 
14079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
14089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
140948a46eb9SPierre 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));
14100588280cSMatthew G. Knepley       }
14110588280cSMatthew G. Knepley     }
14129566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
14139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
14149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
141563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
14169566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
14179566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
14189566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
14199566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
14209566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
14210f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
14220f7d6e4aSStefano Zampini     Vec                    cown, acown;
14230f7d6e4aSStefano Zampini     VecScatter             sct;
14240f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
14250f7d6e4aSStefano Zampini     IS                     gid, acis;
14260f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
14270f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
14280f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
14290f7d6e4aSStefano Zampini     const PetscInt        *idxs;
14300f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
14310f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
14320f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
14330f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
14340f7d6e4aSStefano Zampini 
14359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1437b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
14389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
14390f7d6e4aSStefano Zampini #endif
14400f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
14419566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
14429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
14430f7d6e4aSStefano Zampini       d1 = 0;
14449566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
14450f7d6e4aSStefano Zampini       nid = d2;
14469566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
14479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
14489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
14490f7d6e4aSStefano Zampini     } else nid = 0.0;
14500f7d6e4aSStefano Zampini 
14510f7d6e4aSStefano Zampini     /* Get connectivity */
14529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14539566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
14540f7d6e4aSStefano Zampini 
14550f7d6e4aSStefano Zampini     /* filter overlapped local cells */
14569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
14579566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
14589566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
14599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
14600f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
14610f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
14620f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
14630f7d6e4aSStefano Zampini     }
14649566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
146563a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
14669566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14679566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
14680f7d6e4aSStefano Zampini 
14690f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
14709566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
14719566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
14729566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
14739566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
14740f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
14759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
14769566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
14779566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14789566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
14809566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
14819566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
14820f7d6e4aSStefano Zampini 
14830f7d6e4aSStefano Zampini     /* compute edgeCut */
14840f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
14859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
14869566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
14879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
14889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14899566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
14900f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
14910f7d6e4aSStefano Zampini       PetscInt totl;
14920f7d6e4aSStefano Zampini 
14930f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
14949566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
14950f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
14960f7d6e4aSStefano Zampini         if (work[i] < 0) {
14970f7d6e4aSStefano Zampini           ect += 1;
14980f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
14990f7d6e4aSStefano Zampini         }
15000f7d6e4aSStefano Zampini       }
15010f7d6e4aSStefano Zampini     }
15029566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
15039566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
15040f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
15050f7d6e4aSStefano Zampini     lm[1] = -numVertices;
15061c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
150763a3b9bcSJacob 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]));
15080f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
15090f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
15100f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
15111c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
151263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1513b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
1514f4f49eeaSPierre Jolivet     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.));
15150f7d6e4aSStefano Zampini #else
151663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
15170f7d6e4aSStefano Zampini #endif
15189566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
15199566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
15209566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
15219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1522552f7358SJed Brown   } else {
1523412e9a14SMatthew G. Knepley     const char    *name;
1524d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1525412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1526d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1527ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
15289318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1529412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1530412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1531552f7358SJed Brown 
15329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
15349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
15359566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
15369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
15379566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
153863a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
153963a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
154063a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
15419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
15421c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
15432827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd));
1544d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
15459566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
15469566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1547412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1548412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1549412e9a14SMatthew G. Knepley 
15509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
15519566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1552412e9a14SMatthew G. Knepley       ict = ct0;
15539566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1554412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1555412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1556412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1557412e9a14SMatthew G. Knepley 
15589566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1559412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1560412e9a14SMatthew G. Knepley         else ++Nc[1];
1561412e9a14SMatthew G. Knepley       }
1562ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
15639566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15649566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
15659566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
156663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1567834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1568dd400576SPatrick Sanan           if (rank == 0) {
156963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
157063a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
157163a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1572834065abSMatthew G. Knepley           }
1573cbb7f117SMark Adams         }
1574ca7bf7eeSMatthew G. Knepley       } else {
1575ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1576ca7bf7eeSMatthew G. Knepley 
15779371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
15789371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
15799566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15809371c9d4SSatish Balay         locMinMax[0] = Nc[1];
15819371c9d4SSatish Balay         locMinMax[1] = Nc[1];
15829566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1583ca7bf7eeSMatthew G. Knepley         if (d == depth) {
15849371c9d4SSatish Balay           locMinMax[0] = gcNum;
15859371c9d4SSatish Balay           locMinMax[1] = gcNum;
15869566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1587ca7bf7eeSMatthew G. Knepley         }
158863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
15899566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15909566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
15919566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1592ca7bf7eeSMatthew G. Knepley       }
15939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1594552f7358SJed Brown     }
15959566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
15969318fe57SMatthew G. Knepley     {
15979318fe57SMatthew G. Knepley       const PetscReal *maxCell;
15989318fe57SMatthew G. Knepley       const PetscReal *L;
15996858538eSMatthew G. Knepley       PetscBool        localized;
16009318fe57SMatthew G. Knepley 
16014fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
16029566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
16036858538eSMatthew G. Knepley       if (L || localized) {
16046858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
16059566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
16066858538eSMatthew G. Knepley         if (L) {
16076858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
16089318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
16096858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
16106858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
16119318fe57SMatthew G. Knepley           }
16126858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
16136858538eSMatthew G. Knepley         }
16146858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
16159566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16169318fe57SMatthew G. Knepley       }
16179318fe57SMatthew G. Knepley     }
16189566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
16199566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1620a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1621a57dd577SMatthew G Knepley       DMLabel         label;
1622a57dd577SMatthew G Knepley       const char     *name;
1623a57dd577SMatthew G Knepley       IS              valueIS;
1624a57dd577SMatthew G Knepley       const PetscInt *values;
1625a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1626a57dd577SMatthew G Knepley 
16279566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
16289566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
16299566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
163063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
16319566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
16329566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
16339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1634a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1635a57dd577SMatthew G Knepley         PetscInt size;
1636a57dd577SMatthew G Knepley 
16379566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
16389566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
163963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1640a57dd577SMatthew G Knepley       }
16419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
16429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16439566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
16449566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1645a57dd577SMatthew G Knepley     }
1646c1cad2e7SMatthew G. Knepley     {
1647c1cad2e7SMatthew G. Knepley       char    **labelNames;
1648c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1649c1cad2e7SMatthew G. Knepley       PetscBool flg;
1650c1cad2e7SMatthew G. Knepley 
16519566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
16529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1653c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1654c1cad2e7SMatthew G. Knepley         DMLabel label;
1655c1cad2e7SMatthew G. Knepley 
16569566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1657c1cad2e7SMatthew G. Knepley         if (flg) {
16589566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
16599566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1660c1cad2e7SMatthew G. Knepley         }
16619566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1662c1cad2e7SMatthew G. Knepley       }
16639566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1664c1cad2e7SMatthew G. Knepley     }
166534aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
166634aa8a36SMatthew G. Knepley     if (dm->Nf) {
166734aa8a36SMatthew G. Knepley       PetscInt f;
166834aa8a36SMatthew G. Knepley 
166934aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
167034aa8a36SMatthew G. Knepley         const char *name;
167134aa8a36SMatthew G. Knepley 
16729566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
16739566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
16749566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
16759566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
167634aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
16779566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
16789566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
167934aa8a36SMatthew G. Knepley         } else {
16809566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
16819566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
168234aa8a36SMatthew G. Knepley         }
16839566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
168434aa8a36SMatthew G. Knepley       }
168534aa8a36SMatthew G. Knepley     }
16869566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
16878e7ff633SMatthew G. Knepley     if (cdm) {
16889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
16899f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
16909566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
16919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
16928e7ff633SMatthew G. Knepley     }
1693552f7358SJed Brown   }
16943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1695552f7358SJed Brown }
1696552f7358SJed Brown 
1697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1698d71ae5a4SJacob Faibussowitsch {
1699e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1700e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1701a12d352dSMatthew G. Knepley   PetscInt       cdim;
1702e5c487bfSMatthew G. Knepley 
1703e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
17069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1707e5c487bfSMatthew G. Knepley   switch (ct) {
1708a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1709a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1710a12d352dSMatthew G. Knepley     switch (cdim) {
17119371c9d4SSatish Balay     case 1: {
1712a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1713a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1714a12d352dSMatthew G. Knepley 
17159566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
17169566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
17179566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
17189371c9d4SSatish Balay     } break;
17199371c9d4SSatish Balay     case 2: {
1720a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1721a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1722a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1723a12d352dSMatthew G. Knepley 
17249566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17259566063dSJacob 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));
17269566063dSJacob 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));
17279371c9d4SSatish Balay     } break;
1728d71ae5a4SJacob Faibussowitsch     default:
1729d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1730a12d352dSMatthew G. Knepley     }
1731a12d352dSMatthew G. Knepley     break;
1732e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
17339371c9d4SSatish 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));
17349566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17369566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1737e5c487bfSMatthew G. Knepley     break;
1738e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
17399371c9d4SSatish 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));
17409371c9d4SSatish 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));
17419566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1745e5c487bfSMatthew G. Knepley     break;
17469f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
17479f4ada15SMatthew 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));
17489f4ada15SMatthew 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));
17499f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17509f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17519f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17529f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
17539f4ada15SMatthew G. Knepley     break;
1754d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1755d71ae5a4SJacob Faibussowitsch     break;
1756d71ae5a4SJacob Faibussowitsch   default:
1757d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1758e5c487bfSMatthew G. Knepley   }
17593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1760e5c487bfSMatthew G. Knepley }
1761e5c487bfSMatthew G. Knepley 
1762c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1763d71ae5a4SJacob Faibussowitsch {
1764e5c487bfSMatthew G. Knepley   PetscReal   centroid[2] = {0., 0.};
1765e5c487bfSMatthew G. Knepley   PetscMPIInt rank;
1766c5aedaa3SMatthew G. Knepley   PetscInt    fillColor;
1767e5c487bfSMatthew G. Knepley 
1768e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1770e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1771c5aedaa3SMatthew G. Knepley   for (PetscInt v = 0; v < Nv; ++v) {
1772c5aedaa3SMatthew G. Knepley     centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv;
1773c5aedaa3SMatthew G. Knepley     centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv;
17749371c9d4SSatish Balay   }
1775c5aedaa3SMatthew G. Knepley   for (PetscInt e = 0; e < Nv; ++e) {
1776e5c487bfSMatthew G. Knepley     refCoords[0] = refVertices[e * 2 + 0];
1777e5c487bfSMatthew G. Knepley     refCoords[1] = refVertices[e * 2 + 1];
1778c5aedaa3SMatthew G. Knepley     for (PetscInt d = 1; d <= edgeDiv; ++d) {
1779c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv;
1780c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv;
1781e5c487bfSMatthew G. Knepley     }
17829566063dSJacob Faibussowitsch     PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1783c5aedaa3SMatthew G. Knepley     for (PetscInt d = 0; d < edgeDiv; ++d) {
17849566063dSJacob 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));
17859566063dSJacob 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));
1786e5c487bfSMatthew G. Knepley     }
1787e5c487bfSMatthew G. Knepley   }
1788c5aedaa3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1789c5aedaa3SMatthew G. Knepley }
1790c5aedaa3SMatthew G. Knepley 
1791c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1792c5aedaa3SMatthew G. Knepley {
1793c5aedaa3SMatthew G. Knepley   DMPolytopeType ct;
1794c5aedaa3SMatthew G. Knepley 
1795c5aedaa3SMatthew G. Knepley   PetscFunctionBegin;
1796c5aedaa3SMatthew G. Knepley   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1797c5aedaa3SMatthew G. Knepley   switch (ct) {
1798c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE: {
1799c5aedaa3SMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1800c5aedaa3SMatthew G. Knepley 
1801c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords));
1802c5aedaa3SMatthew G. Knepley   } break;
1803c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL: {
1804c5aedaa3SMatthew G. Knepley     PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.};
1805c5aedaa3SMatthew G. Knepley 
1806c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords));
18079371c9d4SSatish Balay   } break;
1808d71ae5a4SJacob Faibussowitsch   default:
1809d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1810e5c487bfSMatthew G. Knepley   }
18113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1812e5c487bfSMatthew G. Knepley }
1813e5c487bfSMatthew G. Knepley 
1814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1815d71ae5a4SJacob Faibussowitsch {
1816e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1817e412dcbdSMatthew G. Knepley   DM           cdm;
1818e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1819e412dcbdSMatthew G. Knepley   Vec          coordinates;
1820c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1821e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1822c5aedaa3SMatthew G. Knepley   PetscBool    isnull, drawAffine;
1823c5aedaa3SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv;
1824e412dcbdSMatthew G. Knepley 
1825e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
18269566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
182763a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
1828c5aedaa3SMatthew G. Knepley   PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree));
1829c5aedaa3SMatthew G. Knepley   drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE;
1830c5aedaa3SMatthew G. Knepley   edgeDiv    = cDegree + 1;
18319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
18329566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
18339566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
18349566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
18359566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
18369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1838e412dcbdSMatthew G. Knepley 
18399566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
18409566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
18413ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
18429566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1843e412dcbdSMatthew G. Knepley 
1844c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
18459566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
18469566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1847e412dcbdSMatthew G. Knepley 
1848cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1849cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1850c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1851ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1852c9c77995SMatthew G. Knepley     PetscBool          isDG;
1853cf3064d3SMatthew G. Knepley 
1854c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
18551baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
18561baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1857c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1858cf3064d3SMatthew G. Knepley   }
18599566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
18609566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
18619566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
18629566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
18633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1864e412dcbdSMatthew G. Knepley }
1865e412dcbdSMatthew G. Knepley 
1866e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm)
1867e44f6aebSMatthew G. Knepley {
1868e44f6aebSMatthew G. Knepley   DM           odm = dm, rdm = dm, cdm;
1869e44f6aebSMatthew G. Knepley   PetscFE      fe;
1870e44f6aebSMatthew G. Knepley   PetscSpace   sp;
1871e44f6aebSMatthew G. Knepley   PetscClassId id;
1872e44f6aebSMatthew G. Knepley   PetscInt     degree;
1873e44f6aebSMatthew G. Knepley   PetscBool    hoView = PETSC_TRUE;
1874e44f6aebSMatthew G. Knepley 
1875e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
1876e44f6aebSMatthew G. Knepley   PetscObjectOptionsBegin((PetscObject)dm);
1877e44f6aebSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL));
1878e44f6aebSMatthew G. Knepley   PetscOptionsEnd();
1879e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dm));
1880e44f6aebSMatthew G. Knepley   *hdm = dm;
1881e44f6aebSMatthew G. Knepley   if (!hoView) PetscFunctionReturn(PETSC_SUCCESS);
1882e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
1883e44f6aebSMatthew G. Knepley   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
1884e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1885e44f6aebSMatthew G. Knepley   if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS);
1886e44f6aebSMatthew G. Knepley   PetscCall(PetscFEGetBasisSpace(fe, &sp));
1887e44f6aebSMatthew G. Knepley   PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
1888e44f6aebSMatthew G. Knepley   for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) {
1889e44f6aebSMatthew G. Knepley     DM  cdm, rcdm;
1890e44f6aebSMatthew G. Knepley     Mat In;
1891e44f6aebSMatthew G. Knepley     Vec cl, rcl;
1892e44f6aebSMatthew G. Knepley 
1893e44f6aebSMatthew G. Knepley     PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm));
1894c5aedaa3SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL));
1895e44f6aebSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates"));
1896e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(odm, &cdm));
1897e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(rdm, &rcdm));
1898e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(odm, &cl));
1899e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(rdm, &rcl));
1900e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoarseDM(rcdm, cdm));
1901e44f6aebSMatthew G. Knepley     PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL));
1902e44f6aebSMatthew G. Knepley     PetscCall(MatMult(In, cl, rcl));
1903e44f6aebSMatthew G. Knepley     PetscCall(MatDestroy(&In));
1904e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(rdm, rcl));
1905e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&odm));
1906e44f6aebSMatthew G. Knepley     odm = rdm;
1907e44f6aebSMatthew G. Knepley   }
1908e44f6aebSMatthew G. Knepley   *hdm = rdm;
1909e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1910e44f6aebSMatthew G. Knepley }
1911e44f6aebSMatthew G. Knepley 
19121e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19131e50132fSMatthew G. Knepley   #include <exodusII.h>
19146823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
19151e50132fSMatthew G. Knepley #endif
19161e50132fSMatthew G. Knepley 
1917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1918d71ae5a4SJacob Faibussowitsch {
19195f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1920002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1921552f7358SJed Brown 
1922552f7358SJed Brown   PetscFunctionBegin;
1923552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1924552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
19279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
19309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
19315f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1932552f7358SJed Brown   if (iascii) {
19338135c375SStefano Zampini     PetscViewerFormat format;
19349566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
19351baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
19361baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1937c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1938c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
19399566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1940c6ccd67eSMatthew G. Knepley #else
1941c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1942552f7358SJed Brown #endif
1943e412dcbdSMatthew G. Knepley   } else if (isvtk) {
19449566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1945e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1946e44f6aebSMatthew G. Knepley     DM hdm;
1947e44f6aebSMatthew G. Knepley 
1948e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm));
1949e44f6aebSMatthew G. Knepley     PetscCall(DMPlexView_Draw(hdm, viewer));
1950e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&hdm));
19518135c375SStefano Zampini   } else if (isglvis) {
19529566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
19531e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19541e50132fSMatthew G. Knepley   } else if (isexodus) {
19556823f3c5SBlaise Bourdin     /*
19566823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
19576823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1958da81f932SPierre Jolivet       with ID 1, containing all cells.
19596823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
19606823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
19616823f3c5SBlaise Bourdin     */
19626823f3c5SBlaise Bourdin     PetscInt numCS;
19639566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
19646823f3c5SBlaise Bourdin     if (!numCS) {
19651e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
19669566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
19679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
19689566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
19696823f3c5SBlaise Bourdin     }
19709566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
19711e50132fSMatthew G. Knepley #endif
19725f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
19735f34f2dcSJed Brown   } else if (iscgns) {
19745f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
19755f34f2dcSJed Brown #endif
19761baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1977cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
19789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1979cb3ba0daSMatthew G. Knepley   if (flg) {
1980cb3ba0daSMatthew G. Knepley     Vec ranks;
19819566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
19829566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
19839566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1984cb3ba0daSMatthew G. Knepley   }
1985002a2709SMatthew G. Knepley   /* Optionally view a label */
19869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1987002a2709SMatthew G. Knepley   if (flg) {
1988002a2709SMatthew G. Knepley     DMLabel label;
1989002a2709SMatthew G. Knepley     Vec     val;
1990002a2709SMatthew G. Knepley 
19919566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
199228b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
19939566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
19949566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
19959566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1996002a2709SMatthew G. Knepley   }
19973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1998552f7358SJed Brown }
1999552f7358SJed Brown 
20007f96f51bSksagiyam /*@
2001a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
20027f96f51bSksagiyam 
200320f4b53cSBarry Smith   Collective
20047f96f51bSksagiyam 
20057f96f51bSksagiyam   Input Parameters:
2006a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
2007a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
20087f96f51bSksagiyam 
20097f96f51bSksagiyam   Level: advanced
20107f96f51bSksagiyam 
20111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
20127f96f51bSksagiyam @*/
2013d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
2014d71ae5a4SJacob Faibussowitsch {
20157f96f51bSksagiyam   PetscBool ishdf5;
20167f96f51bSksagiyam 
20177f96f51bSksagiyam   PetscFunctionBegin;
20187f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20197f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
20227f96f51bSksagiyam   if (ishdf5) {
20237f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
20247f96f51bSksagiyam     PetscViewerFormat format;
20259566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20267f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20277f96f51bSksagiyam       IS globalPointNumbering;
20287f96f51bSksagiyam 
20299566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
20309566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
20319566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
203298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
20337f96f51bSksagiyam #else
20347f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20357f96f51bSksagiyam #endif
20367f96f51bSksagiyam   }
20379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
20383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20397f96f51bSksagiyam }
20407f96f51bSksagiyam 
204177b8e257Sksagiyam /*@
2042a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
204377b8e257Sksagiyam 
204420f4b53cSBarry Smith   Collective
204577b8e257Sksagiyam 
204677b8e257Sksagiyam   Input Parameters:
2047a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
2048a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
204977b8e257Sksagiyam 
205077b8e257Sksagiyam   Level: advanced
205177b8e257Sksagiyam 
20521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
205377b8e257Sksagiyam @*/
2054d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
2055d71ae5a4SJacob Faibussowitsch {
205677b8e257Sksagiyam   PetscBool ishdf5;
205777b8e257Sksagiyam 
205877b8e257Sksagiyam   PetscFunctionBegin;
205977b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
206077b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
206377b8e257Sksagiyam   if (ishdf5) {
206477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
206577b8e257Sksagiyam     PetscViewerFormat format;
20669566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
206777b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20689566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
2069fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
207077b8e257Sksagiyam #else
207177b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
207277b8e257Sksagiyam #endif
207377b8e257Sksagiyam   }
20749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
20753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207677b8e257Sksagiyam }
207777b8e257Sksagiyam 
2078bd6565f1Sksagiyam /*@
2079a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
2080bd6565f1Sksagiyam 
208120f4b53cSBarry Smith   Collective
2082bd6565f1Sksagiyam 
2083bd6565f1Sksagiyam   Input Parameters:
2084a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
2085a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
2086bd6565f1Sksagiyam 
2087bd6565f1Sksagiyam   Level: advanced
2088bd6565f1Sksagiyam 
20891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
2090bd6565f1Sksagiyam @*/
2091d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
2092d71ae5a4SJacob Faibussowitsch {
2093bd6565f1Sksagiyam   PetscBool ishdf5;
2094bd6565f1Sksagiyam 
2095bd6565f1Sksagiyam   PetscFunctionBegin;
2096bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2097bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
2100bd6565f1Sksagiyam   if (ishdf5) {
2101bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
2102bd6565f1Sksagiyam     IS                globalPointNumbering;
2103bd6565f1Sksagiyam     PetscViewerFormat format;
2104bd6565f1Sksagiyam 
21059566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2106bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21079566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
21089566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
21099566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
211098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2111bd6565f1Sksagiyam #else
2112bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2113bd6565f1Sksagiyam #endif
2114bd6565f1Sksagiyam   }
21159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
21163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2117bd6565f1Sksagiyam }
2118bd6565f1Sksagiyam 
2119021affd3Sksagiyam /*@
2120a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
2121021affd3Sksagiyam 
212220f4b53cSBarry Smith   Collective
2123021affd3Sksagiyam 
2124021affd3Sksagiyam   Input Parameters:
2125a1cb98faSBarry Smith + dm        - The `DM` that contains the topology on which the section to be saved is defined
2126a1cb98faSBarry Smith . viewer    - The `PetscViewer` for saving
21270318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL`
2128021affd3Sksagiyam 
2129021affd3Sksagiyam   Level: advanced
2130021affd3Sksagiyam 
2131021affd3Sksagiyam   Notes:
2132420bcc1bSBarry 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.
2133021affd3Sksagiyam 
21340318f8a0SStefano Zampini   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 (or in case `sectiondm` is `NULL`) 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.
2135021affd3Sksagiyam 
21361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
2137021affd3Sksagiyam @*/
2138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
2139d71ae5a4SJacob Faibussowitsch {
2140021affd3Sksagiyam   PetscBool ishdf5;
2141021affd3Sksagiyam 
2142021affd3Sksagiyam   PetscFunctionBegin;
2143021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2144021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21450318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2146021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
2149021affd3Sksagiyam   if (ishdf5) {
2150021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
21519566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
2152021affd3Sksagiyam #else
2153021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2154021affd3Sksagiyam #endif
2155021affd3Sksagiyam   }
21569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
21573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2158021affd3Sksagiyam }
2159021affd3Sksagiyam 
21603e97647fSksagiyam /*@
21613e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
21623e97647fSksagiyam 
216320f4b53cSBarry Smith   Collective
21643e97647fSksagiyam 
21653e97647fSksagiyam   Input Parameters:
2166a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2167a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
21680318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
21693e97647fSksagiyam - vec       - The global vector to be saved
21703e97647fSksagiyam 
21713e97647fSksagiyam   Level: advanced
21723e97647fSksagiyam 
21733e97647fSksagiyam   Notes:
21740318f8a0SStefano Zampini   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 (or in case `sectiondm` is `NULL`) 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.
21753e97647fSksagiyam 
217660225df5SJacob Faibussowitsch   Calling sequence:
2177a1cb98faSBarry Smith .vb
2178a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2179a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2180a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2181a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2182a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2183a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2184a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2185a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2186a1cb98faSBarry Smith        PetscSectionSetUp(section);
2187a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2188a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2189a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2190a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2191a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2192a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2193a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2194a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2195a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2196a1cb98faSBarry Smith        DMDestroy(&dm);
2197a1cb98faSBarry Smith .ve
21983e97647fSksagiyam 
21991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22003e97647fSksagiyam @*/
2201d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2202d71ae5a4SJacob Faibussowitsch {
22033e97647fSksagiyam   PetscBool ishdf5;
22043e97647fSksagiyam 
22053e97647fSksagiyam   PetscFunctionBegin;
22063e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22073e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22080318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22093e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22103e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22113e97647fSksagiyam   /* Check consistency */
22123e97647fSksagiyam   {
22133e97647fSksagiyam     PetscSection section;
22143e97647fSksagiyam     PetscBool    includesConstraints;
22153e97647fSksagiyam     PetscInt     m, m1;
22163e97647fSksagiyam 
22179566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22189566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
22199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22209566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22219566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
222263a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
22233e97647fSksagiyam   }
22249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22263e97647fSksagiyam   if (ishdf5) {
22273e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
22289566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
22293e97647fSksagiyam #else
22303e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22313e97647fSksagiyam #endif
22323e97647fSksagiyam   }
22339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22353e97647fSksagiyam }
22363e97647fSksagiyam 
22373e97647fSksagiyam /*@
22383e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
22393e97647fSksagiyam 
224020f4b53cSBarry Smith   Collective
22413e97647fSksagiyam 
22423e97647fSksagiyam   Input Parameters:
2243a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2244a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
22450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL`
22463e97647fSksagiyam - vec       - The local vector to be saved
22473e97647fSksagiyam 
22483e97647fSksagiyam   Level: advanced
22493e97647fSksagiyam 
2250a1cb98faSBarry Smith   Note:
22510318f8a0SStefano Zampini   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 (or in case `sectiondm` is `NULL`) 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.
22523e97647fSksagiyam 
225360225df5SJacob Faibussowitsch   Calling sequence:
2254a1cb98faSBarry Smith .vb
2255a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2256a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2257a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2258a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2259a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2260a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2261a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2262a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2263a1cb98faSBarry Smith        PetscSectionSetUp(section);
2264a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2265a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2266a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2267a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2268a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2269a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2270a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2271a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2272a1cb98faSBarry Smith        DMDestroy(&dm);
2273a1cb98faSBarry Smith .ve
22743e97647fSksagiyam 
22751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22763e97647fSksagiyam @*/
2277d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2278d71ae5a4SJacob Faibussowitsch {
22793e97647fSksagiyam   PetscBool ishdf5;
22803e97647fSksagiyam 
22813e97647fSksagiyam   PetscFunctionBegin;
22823e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22833e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22840318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22853e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22863e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22873e97647fSksagiyam   /* Check consistency */
22883e97647fSksagiyam   {
22893e97647fSksagiyam     PetscSection section;
22903e97647fSksagiyam     PetscBool    includesConstraints;
22913e97647fSksagiyam     PetscInt     m, m1;
22923e97647fSksagiyam 
22939566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22949566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
22959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22969566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22979566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
229863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
22993e97647fSksagiyam   }
23009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23023e97647fSksagiyam   if (ishdf5) {
23033e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
23049566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
23053e97647fSksagiyam #else
23063e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23073e97647fSksagiyam #endif
23083e97647fSksagiyam   }
23099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23113e97647fSksagiyam }
23123e97647fSksagiyam 
2313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2314d71ae5a4SJacob Faibussowitsch {
2315d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
23162c40f234SMatthew G. Knepley 
23172c40f234SMatthew G. Knepley   PetscFunctionBegin;
23182c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23192c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2321d4f5a9a0SVaclav Hapla   if (ishdf5) {
23222c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
23239c48423bSVaclav Hapla     PetscViewerFormat format;
23249566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23259c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
23269566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2327509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23289566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
232998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
23303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23312c40f234SMatthew G. Knepley #else
23322c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2333552f7358SJed Brown #endif
233498921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2335552f7358SJed Brown }
2336552f7358SJed Brown 
2337ea8e1828Sksagiyam /*@
2338a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2339ea8e1828Sksagiyam 
234020f4b53cSBarry Smith   Collective
2341ea8e1828Sksagiyam 
2342ea8e1828Sksagiyam   Input Parameters:
2343a1cb98faSBarry Smith + dm     - The `DM` into which the topology is loaded
2344a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology
2345ea8e1828Sksagiyam 
23462fe279fdSBarry Smith   Output Parameter:
234720f4b53cSBarry 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
2348dec9e869Sksagiyam 
2349ea8e1828Sksagiyam   Level: advanced
2350ea8e1828Sksagiyam 
23511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2352a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2353ea8e1828Sksagiyam @*/
2354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2355d71ae5a4SJacob Faibussowitsch {
2356ea8e1828Sksagiyam   PetscBool ishdf5;
2357ea8e1828Sksagiyam 
2358ea8e1828Sksagiyam   PetscFunctionBegin;
2359ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2360ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23614f572ea9SToby Isaac   if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3);
23629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2364ea8e1828Sksagiyam   if (ishdf5) {
2365ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2366ea8e1828Sksagiyam     PetscViewerFormat format;
23679566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2368ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23699566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
237098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2371ea8e1828Sksagiyam #else
2372ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2373ea8e1828Sksagiyam #endif
2374ea8e1828Sksagiyam   }
23759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
23763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2377ea8e1828Sksagiyam }
2378ea8e1828Sksagiyam 
23793e701f1cSksagiyam /*@
2380a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
23813e701f1cSksagiyam 
238220f4b53cSBarry Smith   Collective
23833e701f1cSksagiyam 
23843e701f1cSksagiyam   Input Parameters:
2385a1cb98faSBarry Smith + dm                   - The `DM` into which the coordinates are loaded
2386a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved coordinates
2387a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
23883e701f1cSksagiyam 
23893e701f1cSksagiyam   Level: advanced
23903e701f1cSksagiyam 
23911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2392a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
23933e701f1cSksagiyam @*/
2394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2395d71ae5a4SJacob Faibussowitsch {
23963e701f1cSksagiyam   PetscBool ishdf5;
23973e701f1cSksagiyam 
23983e701f1cSksagiyam   PetscFunctionBegin;
23993e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24003e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2401c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24043e701f1cSksagiyam   if (ishdf5) {
24053e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
24063e701f1cSksagiyam     PetscViewerFormat format;
24079566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
24083e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24099566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
241098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
24113e701f1cSksagiyam #else
24123e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24133e701f1cSksagiyam #endif
24143e701f1cSksagiyam   }
24159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24173e701f1cSksagiyam }
24183e701f1cSksagiyam 
2419b08ad5deSksagiyam /*@
2420a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2421b08ad5deSksagiyam 
242220f4b53cSBarry Smith   Collective
2423b08ad5deSksagiyam 
2424b08ad5deSksagiyam   Input Parameters:
2425a1cb98faSBarry Smith + dm                   - The `DM` into which the labels are loaded
2426a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved labels
242720f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2428b08ad5deSksagiyam 
2429b08ad5deSksagiyam   Level: advanced
2430b08ad5deSksagiyam 
2431a1cb98faSBarry Smith   Note:
2432a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2433e6368b79SVaclav Hapla 
24341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2435a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2436b08ad5deSksagiyam @*/
2437d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2438d71ae5a4SJacob Faibussowitsch {
2439b08ad5deSksagiyam   PetscBool ishdf5;
2440b08ad5deSksagiyam 
2441b08ad5deSksagiyam   PetscFunctionBegin;
2442b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2443b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2444e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2447b08ad5deSksagiyam   if (ishdf5) {
2448b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2449b08ad5deSksagiyam     PetscViewerFormat format;
2450b08ad5deSksagiyam 
24519566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2452b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24539566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
245498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2455b08ad5deSksagiyam #else
2456b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2457b08ad5deSksagiyam #endif
2458b08ad5deSksagiyam   }
24599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
24603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2461b08ad5deSksagiyam }
2462b08ad5deSksagiyam 
2463f84dd6b4Sksagiyam /*@
2464a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2465f84dd6b4Sksagiyam 
246620f4b53cSBarry Smith   Collective
2467f84dd6b4Sksagiyam 
2468f84dd6b4Sksagiyam   Input Parameters:
2469a1cb98faSBarry Smith + dm                   - The `DM` that represents the topology
2470a1cb98faSBarry Smith . viewer               - The `PetscViewer` that represents the on-disk section (sectionA)
24710318f8a0SStefano Zampini . sectiondm            - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL`
2472a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2473f84dd6b4Sksagiyam 
2474a4e35b19SJacob Faibussowitsch   Output Parameters:
247520f4b53cSBarry 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)
247620f4b53cSBarry 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)
2477f84dd6b4Sksagiyam 
2478f84dd6b4Sksagiyam   Level: advanced
2479f84dd6b4Sksagiyam 
2480f84dd6b4Sksagiyam   Notes:
248120f4b53cSBarry 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.
2482f84dd6b4Sksagiyam 
24830318f8a0SStefano Zampini   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 (or in case `sectiondm` is `NULL`) 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.
2484f84dd6b4Sksagiyam 
248520f4b53cSBarry 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.
2486f84dd6b4Sksagiyam 
2487f84dd6b4Sksagiyam   Example using 2 processes:
2488a1cb98faSBarry Smith .vb
2489a1cb98faSBarry Smith   NX (number of points on dm): 4
2490a1cb98faSBarry Smith   sectionA                   : the on-disk section
2491a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2492a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2493a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2494a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2495f84dd6b4Sksagiyam 
2496a1cb98faSBarry Smith                                      rank 0    rank 1
2497a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2498a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2499a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2500a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2501a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2502a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2503a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2504a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2505a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2506a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2507a1cb98faSBarry Smith .ve
2508a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2509a1cb98faSBarry Smith 
25101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2511f84dd6b4Sksagiyam @*/
2512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2513d71ae5a4SJacob Faibussowitsch {
2514f84dd6b4Sksagiyam   PetscBool ishdf5;
2515f84dd6b4Sksagiyam 
2516f84dd6b4Sksagiyam   PetscFunctionBegin;
2517f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2518f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25190318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2520f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2521f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
25224f572ea9SToby Isaac   if (globalDofSF) PetscAssertPointer(globalDofSF, 5);
25234f572ea9SToby Isaac   if (localDofSF) PetscAssertPointer(localDofSF, 6);
25249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2526f84dd6b4Sksagiyam   if (ishdf5) {
2527f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
25289566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2529f84dd6b4Sksagiyam #else
2530f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2531f84dd6b4Sksagiyam #endif
2532f84dd6b4Sksagiyam   }
25339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
25343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2535f84dd6b4Sksagiyam }
2536f84dd6b4Sksagiyam 
25378be3dfe1Sksagiyam /*@
25388be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
25398be3dfe1Sksagiyam 
254020f4b53cSBarry Smith   Collective
25418be3dfe1Sksagiyam 
25428be3dfe1Sksagiyam   Input Parameters:
2543a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2544a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
25450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
2546a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
25478be3dfe1Sksagiyam - vec       - The global vector to set values of
25488be3dfe1Sksagiyam 
25498be3dfe1Sksagiyam   Level: advanced
25508be3dfe1Sksagiyam 
25518be3dfe1Sksagiyam   Notes:
25520318f8a0SStefano Zampini   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 (or in case `sectiondm` is `NULL`) 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.
25538be3dfe1Sksagiyam 
255460225df5SJacob Faibussowitsch   Calling sequence:
2555a1cb98faSBarry Smith .vb
2556a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2557a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2558a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2559a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2560a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2561a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2562a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2563a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2564a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2565a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2566a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2567a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2568a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2569a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2570a1cb98faSBarry Smith        DMDestroy(&dm);
2571a1cb98faSBarry Smith .ve
25728be3dfe1Sksagiyam 
25731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2574a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
25758be3dfe1Sksagiyam @*/
2576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2577d71ae5a4SJacob Faibussowitsch {
25788be3dfe1Sksagiyam   PetscBool ishdf5;
25798be3dfe1Sksagiyam 
25808be3dfe1Sksagiyam   PetscFunctionBegin;
25818be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25828be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25830318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
25848be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
25858be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
25868be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
25878be3dfe1Sksagiyam   /* Check consistency */
25888be3dfe1Sksagiyam   {
25898be3dfe1Sksagiyam     PetscSection section;
25908be3dfe1Sksagiyam     PetscBool    includesConstraints;
25918be3dfe1Sksagiyam     PetscInt     m, m1;
25928be3dfe1Sksagiyam 
25939566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25949566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
25959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25969566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25979566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
259863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
25998be3dfe1Sksagiyam   }
26009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26028be3dfe1Sksagiyam   if (ishdf5) {
26038be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26049566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26058be3dfe1Sksagiyam #else
26068be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26078be3dfe1Sksagiyam #endif
26088be3dfe1Sksagiyam   }
26099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26118be3dfe1Sksagiyam }
26128be3dfe1Sksagiyam 
26138be3dfe1Sksagiyam /*@
26148be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
26158be3dfe1Sksagiyam 
261620f4b53cSBarry Smith   Collective
26178be3dfe1Sksagiyam 
26188be3dfe1Sksagiyam   Input Parameters:
2619a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2620a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
26210318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL`
2622a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
26238be3dfe1Sksagiyam - vec       - The local vector to set values of
26248be3dfe1Sksagiyam 
26258be3dfe1Sksagiyam   Level: advanced
26268be3dfe1Sksagiyam 
26278be3dfe1Sksagiyam   Notes:
26280318f8a0SStefano Zampini   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 (or in case `sectiondm` is `NULL`) 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.
26298be3dfe1Sksagiyam 
263060225df5SJacob Faibussowitsch   Calling sequence:
2631a1cb98faSBarry Smith .vb
2632a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2633a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2634a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2635a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2636a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2637a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2638a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2639a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2640a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2641a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2642a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2643a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2644a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2645a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2646a1cb98faSBarry Smith        DMDestroy(&dm);
2647a1cb98faSBarry Smith .ve
26488be3dfe1Sksagiyam 
26491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2650a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
26518be3dfe1Sksagiyam @*/
2652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2653d71ae5a4SJacob Faibussowitsch {
26548be3dfe1Sksagiyam   PetscBool ishdf5;
26558be3dfe1Sksagiyam 
26568be3dfe1Sksagiyam   PetscFunctionBegin;
26578be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26588be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
26590318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
26608be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
26618be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
26628be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
26638be3dfe1Sksagiyam   /* Check consistency */
26648be3dfe1Sksagiyam   {
26658be3dfe1Sksagiyam     PetscSection section;
26668be3dfe1Sksagiyam     PetscBool    includesConstraints;
26678be3dfe1Sksagiyam     PetscInt     m, m1;
26688be3dfe1Sksagiyam 
26699566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
26709566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
26719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
26729566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
26739566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
267463a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
26758be3dfe1Sksagiyam   }
26769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26788be3dfe1Sksagiyam   if (ishdf5) {
26798be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26809566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26818be3dfe1Sksagiyam #else
26828be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26838be3dfe1Sksagiyam #endif
26848be3dfe1Sksagiyam   }
26859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26878be3dfe1Sksagiyam }
26888be3dfe1Sksagiyam 
2689d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2690d71ae5a4SJacob Faibussowitsch {
2691552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2692552f7358SJed Brown 
2693552f7358SJed Brown   PetscFunctionBegin;
26949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
26959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
26969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
26979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
26986c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL));
26992e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
27002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
27012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
27022e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
27036bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
27046bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2705adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL));
2706adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL));
2707adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL));
2708adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL));
2709c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2710c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
2711d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL));
2712d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL));
27135f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
27143ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
27159566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
27169566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
27179566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
27189566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
27199566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
27209566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
272121027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
27229f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
27239566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
27249566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
27259566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
27261d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
27279566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
27289566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
27299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
27309566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
27319566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
27324e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
27336725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
27346725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
27359566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
27369566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
27379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
27389566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
27399566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
27409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
27419566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
27429566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
27439566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
27449566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
27459566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2746552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
27479566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
27483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2749552f7358SJed Brown }
2750552f7358SJed Brown 
2751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2752d71ae5a4SJacob Faibussowitsch {
2753d02c7345SMatthew G. Knepley   PetscSection           sectionGlobal, sectionLocal;
2754acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
27559fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2756837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2757b412c318SBarry Smith   MatType                mtype;
27581428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2759552f7358SJed Brown 
2760552f7358SJed Brown   PetscFunctionBegin;
27619566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2762b412c318SBarry Smith   mtype = dm->mattype;
2763d02c7345SMatthew G. Knepley   PetscCall(DMGetLocalSection(dm, &sectionLocal));
27649566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
27659566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
27669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
27679fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
27689566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
27699566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
27709566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
27719566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
27729566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2773acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
27749566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
27759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
27769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
27779566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
27789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
27799566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
27809566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
27819566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2782552f7358SJed Brown   if (!isShell) {
2783837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
27849fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2785863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2786552f7358SJed Brown 
27879566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
27889fca9976SJed Brown 
27899fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
27909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2791863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2792e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2793863027abSJed Brown       switch (dm->blocking_type) {
27940e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
27959fca9976SJed Brown         PetscInt bdof, offset;
2796a9d99c84SMatthew G. Knepley 
27979566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
27989fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
27999566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
2800d02c7345SMatthew G. Knepley         for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof;
2801d02c7345SMatthew G. Knepley         // Signal block concatenation
2802d02c7345SMatthew G. Knepley         if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof);
28031d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
28041d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
28051d17a0a3SMatthew G. Knepley         if (dof) {
28069371c9d4SSatish Balay           if (bs < 0) {
28079371c9d4SSatish Balay             bs = bdof;
28089371c9d4SSatish Balay           } else if (bs != bdof) {
28099371c9d4SSatish Balay             bs = 1;
28109371c9d4SSatish Balay           }
2811552f7358SJed Brown         }
2812863027abSJed Brown       } break;
2813863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2814863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2815863027abSJed Brown           PetscInt num_comp, bdof, offset;
2816863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2817863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2818863027abSJed Brown           if (dof < 0) continue;
2819863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2820863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2821863027abSJed 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);
2822863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2823863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2824863027abSJed Brown           // Handle possibly constant block size (unlikely)
2825863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2826863027abSJed Brown           if (dof) {
2827863027abSJed Brown             if (bs < 0) {
2828863027abSJed Brown               bs = bdof;
2829863027abSJed Brown             } else if (bs != bdof) {
2830863027abSJed Brown               bs = 1;
2831863027abSJed Brown             }
2832863027abSJed Brown           }
2833863027abSJed Brown         }
2834863027abSJed Brown       } break;
2835863027abSJed Brown       }
28362a28c762SMatthew G Knepley     }
28372a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2838e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2839e432b41dSStefano Zampini     bsLocal[1] = bs;
28409566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2841e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2842e432b41dSStefano Zampini     else bs = bsMinMax[0];
28436fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
28449566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
28450682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
28469566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
28479566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
28480682b8bbSJed Brown     } else {
28499566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
28509566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
28519566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2852552f7358SJed Brown     }
28539fca9976SJed Brown     { // Consolidate blocks
28549fca9976SJed Brown       PetscInt nblocks = 0;
28559fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
28569fca9976SJed Brown         if (pblocks[i] == 0) continue;
2857d02c7345SMatthew G. Knepley         // Negative block size indicates the blocks should be concatenated
2858d02c7345SMatthew G. Knepley         if (pblocks[i] < 0) {
2859d02c7345SMatthew G. Knepley           pblocks[i] = -pblocks[i];
2860d02c7345SMatthew G. Knepley           pblocks[nblocks - 1] += pblocks[i];
2861d02c7345SMatthew G. Knepley         } else {
28629fca9976SJed Brown           pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2863d02c7345SMatthew G. Knepley         }
2864ad540459SPierre 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]);
28659fca9976SJed Brown       }
28669fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
28679fca9976SJed Brown     }
28689fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2869aa0f6e3cSJed Brown   }
28709566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
28713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2872552f7358SJed Brown }
2873552f7358SJed Brown 
28747cd05799SMatthew G. Knepley /*@
2875a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2876be36d101SStefano Zampini 
2877a1cb98faSBarry Smith   Not Collective
2878be36d101SStefano Zampini 
2879be36d101SStefano Zampini   Input Parameter:
288060225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2881be36d101SStefano Zampini 
28822fe279fdSBarry Smith   Output Parameter:
2883be36d101SStefano Zampini . subsection - The subdomain section
2884be36d101SStefano Zampini 
2885be36d101SStefano Zampini   Level: developer
2886be36d101SStefano Zampini 
28871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
28887cd05799SMatthew G. Knepley @*/
2889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2890d71ae5a4SJacob Faibussowitsch {
2891be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2892be36d101SStefano Zampini 
2893be36d101SStefano Zampini   PetscFunctionBegin;
2894be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2895be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2896be36d101SStefano Zampini     PetscSection section;
2897be36d101SStefano Zampini     PetscSF      sf;
2898be36d101SStefano Zampini 
28999566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
29009566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
2901eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
29029566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2903be36d101SStefano Zampini   }
2904be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
29053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2906be36d101SStefano Zampini }
2907be36d101SStefano Zampini 
2908552f7358SJed Brown /*@
290920f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2910552f7358SJed Brown 
2911a1cb98faSBarry Smith   Not Collective
2912552f7358SJed Brown 
2913552f7358SJed Brown   Input Parameter:
291460225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2915552f7358SJed Brown 
2916552f7358SJed Brown   Output Parameters:
2917552f7358SJed Brown + pStart - The first mesh point
2918552f7358SJed Brown - pEnd   - The upper bound for mesh points
2919552f7358SJed Brown 
2920552f7358SJed Brown   Level: beginner
2921552f7358SJed Brown 
29221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2923552f7358SJed Brown @*/
2924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2925d71ae5a4SJacob Faibussowitsch {
2926552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2927552f7358SJed Brown 
2928552f7358SJed Brown   PetscFunctionBegin;
2929552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29309f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
29319f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
29323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2933552f7358SJed Brown }
2934552f7358SJed Brown 
2935552f7358SJed Brown /*@
293620f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2937552f7358SJed Brown 
2938a1cb98faSBarry Smith   Not Collective
2939552f7358SJed Brown 
2940552f7358SJed Brown   Input Parameters:
294160225df5SJacob Faibussowitsch + dm     - The `DMPLEX`
2942552f7358SJed Brown . pStart - The first mesh point
2943552f7358SJed Brown - pEnd   - The upper bound for mesh points
2944552f7358SJed Brown 
2945552f7358SJed Brown   Level: beginner
2946552f7358SJed Brown 
29471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2948552f7358SJed Brown @*/
2949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2950d71ae5a4SJacob Faibussowitsch {
2951552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2952552f7358SJed Brown 
2953552f7358SJed Brown   PetscFunctionBegin;
2954552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
29569566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
295721027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
29583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2959552f7358SJed Brown }
2960552f7358SJed Brown 
2961552f7358SJed Brown /*@
2962eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2963552f7358SJed Brown 
2964a1cb98faSBarry Smith   Not Collective
2965552f7358SJed Brown 
2966552f7358SJed Brown   Input Parameters:
296760225df5SJacob Faibussowitsch + dm - The `DMPLEX`
2968a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2969552f7358SJed Brown 
2970552f7358SJed Brown   Output Parameter:
297120f4b53cSBarry Smith . size - The cone size for point `p`
2972552f7358SJed Brown 
2973552f7358SJed Brown   Level: beginner
2974552f7358SJed Brown 
29751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2976552f7358SJed Brown @*/
2977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2978d71ae5a4SJacob Faibussowitsch {
2979552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2980552f7358SJed Brown 
2981552f7358SJed Brown   PetscFunctionBegin;
2982552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29834f572ea9SToby Isaac   PetscAssertPointer(size, 3);
29849f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
29859f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
29863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2987552f7358SJed Brown }
2988552f7358SJed Brown 
2989552f7358SJed Brown /*@
2990eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2991552f7358SJed Brown 
2992a1cb98faSBarry Smith   Not Collective
2993552f7358SJed Brown 
2994552f7358SJed Brown   Input Parameters:
299560225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
2996a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
299720f4b53cSBarry Smith - size - The cone size for point `p`
2998552f7358SJed Brown 
2999552f7358SJed Brown   Level: beginner
3000552f7358SJed Brown 
3001a1cb98faSBarry Smith   Note:
3002a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
3003a1cb98faSBarry Smith 
30041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
3005552f7358SJed Brown @*/
3006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
3007d71ae5a4SJacob Faibussowitsch {
3008552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3009552f7358SJed Brown 
3010552f7358SJed Brown   PetscFunctionBegin;
3011552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30129f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
30139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
30143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3015552f7358SJed Brown }
3016552f7358SJed Brown 
3017552f7358SJed Brown /*@C
3018eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
3019552f7358SJed Brown 
3020a1cb98faSBarry Smith   Not Collective
3021552f7358SJed Brown 
3022552f7358SJed Brown   Input Parameters:
3023a1cb98faSBarry Smith + dm - The `DMPLEX`
3024a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3025552f7358SJed Brown 
3026552f7358SJed Brown   Output Parameter:
302720f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
3028552f7358SJed Brown 
3029552f7358SJed Brown   Level: beginner
3030552f7358SJed Brown 
303160225df5SJacob Faibussowitsch   Fortran Notes:
3032a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
3033a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
30343813dfbdSMatthew G Knepley 
30351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
3036552f7358SJed Brown @*/
3037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
3038d71ae5a4SJacob Faibussowitsch {
3039552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3040552f7358SJed Brown   PetscInt off;
3041552f7358SJed Brown 
3042552f7358SJed Brown   PetscFunctionBegin;
3043552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30444f572ea9SToby Isaac   PetscAssertPointer(cone, 3);
30459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30468e3a54c0SPierre Jolivet   *cone = PetscSafePointerPlusOffset(mesh->cones, off);
30473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3048552f7358SJed Brown }
3049552f7358SJed Brown 
30500ce7577fSVaclav Hapla /*@C
30510ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
30520ce7577fSVaclav Hapla 
3053a1cb98faSBarry Smith   Not Collective
30540ce7577fSVaclav Hapla 
30550ce7577fSVaclav Hapla   Input Parameters:
3056a1cb98faSBarry Smith + dm - The `DMPLEX`
3057a1cb98faSBarry Smith - p  - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
30580ce7577fSVaclav Hapla 
3059d8d19677SJose E. Roman   Output Parameters:
306020f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
306120f4b53cSBarry Smith - pCones        - An array of points which are on the in-edges for the point set `p`
30620ce7577fSVaclav Hapla 
30630ce7577fSVaclav Hapla   Level: intermediate
30640ce7577fSVaclav Hapla 
30651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
30660ce7577fSVaclav Hapla @*/
3067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
3068d71ae5a4SJacob Faibussowitsch {
30690ce7577fSVaclav Hapla   PetscSection cs, newcs;
30700ce7577fSVaclav Hapla   PetscInt    *cones;
30710ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
30720ce7577fSVaclav Hapla   PetscInt     n;
30730ce7577fSVaclav Hapla 
30740ce7577fSVaclav Hapla   PetscFunctionBegin;
30759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
30769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
30779566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
30780ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
30790ce7577fSVaclav Hapla   if (pCones) {
30809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
30819566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
30820ce7577fSVaclav Hapla   }
30833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30840ce7577fSVaclav Hapla }
30850ce7577fSVaclav Hapla 
3086af9eab45SVaclav Hapla /*@
3087af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
3088d4636a37SVaclav Hapla 
3089a1cb98faSBarry Smith   Not Collective
3090d4636a37SVaclav Hapla 
3091d4636a37SVaclav Hapla   Input Parameters:
3092a1cb98faSBarry Smith + dm     - The `DMPLEX`
3093a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3094d4636a37SVaclav Hapla 
3095d4636a37SVaclav Hapla   Output Parameter:
3096af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
3097d4636a37SVaclav Hapla 
3098d4636a37SVaclav Hapla   Level: advanced
3099d4636a37SVaclav Hapla 
3100af9eab45SVaclav Hapla   Notes:
310120f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
3102af9eab45SVaclav Hapla 
3103a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
3104a1cb98faSBarry Smith 
31051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
3106a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
3107d4636a37SVaclav Hapla @*/
3108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
3109d71ae5a4SJacob Faibussowitsch {
3110af9eab45SVaclav Hapla   IS      *expandedPointsAll;
3111af9eab45SVaclav Hapla   PetscInt depth;
3112d4636a37SVaclav Hapla 
3113d4636a37SVaclav Hapla   PetscFunctionBegin;
3114af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3115af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31164f572ea9SToby Isaac   PetscAssertPointer(expandedPoints, 3);
31179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
3118af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
31199566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
31209566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
31213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3122af9eab45SVaclav Hapla }
3123af9eab45SVaclav Hapla 
3124af9eab45SVaclav Hapla /*@
3125af9eab45SVaclav 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).
3126af9eab45SVaclav Hapla 
3127a1cb98faSBarry Smith   Not Collective
3128af9eab45SVaclav Hapla 
3129af9eab45SVaclav Hapla   Input Parameters:
3130a1cb98faSBarry Smith + dm     - The `DMPLEX`
3131a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3132af9eab45SVaclav Hapla 
3133d8d19677SJose E. Roman   Output Parameters:
3134a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3135af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
3136af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3137af9eab45SVaclav Hapla 
3138af9eab45SVaclav Hapla   Level: advanced
3139af9eab45SVaclav Hapla 
3140af9eab45SVaclav Hapla   Notes:
3141a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
3142af9eab45SVaclav Hapla 
3143a4e35b19SJacob 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.
3144af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
3145af9eab45SVaclav Hapla 
3146a4e35b19SJacob 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\:
3147a4e35b19SJacob Faibussowitsch   (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
3148a4e35b19SJacob Faibussowitsch   (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
3149af9eab45SVaclav Hapla 
31501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3151a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
3152af9eab45SVaclav Hapla @*/
3153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3154d71ae5a4SJacob Faibussowitsch {
3155af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
3156af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
3157af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
3158af9eab45SVaclav Hapla   IS             *expandedPoints_;
3159af9eab45SVaclav Hapla   PetscSection   *sections_;
3160af9eab45SVaclav Hapla 
3161af9eab45SVaclav Hapla   PetscFunctionBegin;
3162af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3163af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31644f572ea9SToby Isaac   if (depth) PetscAssertPointer(depth, 3);
31654f572ea9SToby Isaac   if (expandedPoints) PetscAssertPointer(expandedPoints, 4);
31664f572ea9SToby Isaac   if (sections) PetscAssertPointer(sections, 5);
31679566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
31689566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
31699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
31709566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
31719566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
3172af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
3173af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
31749566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
31759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
3176af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
3178af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
31799566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
31809566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
3181af9eab45SVaclav Hapla       } else {
31829566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
3183af9eab45SVaclav Hapla       }
3184af9eab45SVaclav Hapla     }
31859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
31869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
31879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
3188af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
31909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
3191af9eab45SVaclav Hapla       if (cn > 1) {
31929566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
31939566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3194af9eab45SVaclav Hapla       } else {
3195af9eab45SVaclav Hapla         newarr[co] = arr[i];
3196af9eab45SVaclav Hapla       }
3197af9eab45SVaclav Hapla     }
31989566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3199af9eab45SVaclav Hapla     arr = newarr;
3200af9eab45SVaclav Hapla     n   = newn;
3201af9eab45SVaclav Hapla   }
32029566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3203af9eab45SVaclav Hapla   *depth = depth_;
3204af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3205af9eab45SVaclav Hapla   else {
32069566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
32079566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3208af9eab45SVaclav Hapla   }
3209af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3210af9eab45SVaclav Hapla   else {
32119566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
32129566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3213af9eab45SVaclav Hapla   }
32143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3215af9eab45SVaclav Hapla }
3216af9eab45SVaclav Hapla 
3217af9eab45SVaclav Hapla /*@
3218a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3219af9eab45SVaclav Hapla 
3220a1cb98faSBarry Smith   Not Collective
3221af9eab45SVaclav Hapla 
3222af9eab45SVaclav Hapla   Input Parameters:
3223a1cb98faSBarry Smith + dm     - The `DMPLEX`
3224a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3225af9eab45SVaclav Hapla 
3226d8d19677SJose E. Roman   Output Parameters:
3227a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3228af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3229af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3230af9eab45SVaclav Hapla 
3231af9eab45SVaclav Hapla   Level: advanced
3232af9eab45SVaclav Hapla 
3233a1cb98faSBarry Smith   Note:
3234a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3235af9eab45SVaclav Hapla 
32361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3237a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3238af9eab45SVaclav Hapla @*/
3239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3240d71ae5a4SJacob Faibussowitsch {
3241af9eab45SVaclav Hapla   PetscInt d, depth_;
3242af9eab45SVaclav Hapla 
3243af9eab45SVaclav Hapla   PetscFunctionBegin;
32449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
32451dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3246af9eab45SVaclav Hapla   if (depth) *depth = 0;
3247af9eab45SVaclav Hapla   if (expandedPoints) {
32489566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
32499566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3250af9eab45SVaclav Hapla   }
3251af9eab45SVaclav Hapla   if (sections) {
32529566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
32539566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3254af9eab45SVaclav Hapla   }
32553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3256d4636a37SVaclav Hapla }
3257d4636a37SVaclav Hapla 
3258552f7358SJed Brown /*@
325992371b87SBarry 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
3260552f7358SJed Brown 
3261a1cb98faSBarry Smith   Not Collective
3262552f7358SJed Brown 
3263552f7358SJed Brown   Input Parameters:
326460225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3265a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
326620f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3267552f7358SJed Brown 
3268552f7358SJed Brown   Level: beginner
3269552f7358SJed Brown 
3270a1cb98faSBarry Smith   Note:
3271a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3272a1cb98faSBarry Smith 
32731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3274552f7358SJed Brown @*/
3275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3276d71ae5a4SJacob Faibussowitsch {
3277552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3278552f7358SJed Brown   PetscInt dof, off, c;
3279552f7358SJed Brown 
3280552f7358SJed Brown   PetscFunctionBegin;
3281552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32834f572ea9SToby Isaac   if (dof) PetscAssertPointer(cone, 3);
32849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3285db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3286db485b19SStefano Zampini     PetscInt pStart, pEnd;
3287db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
328863a3b9bcSJacob 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);
3289552f7358SJed Brown     for (c = 0; c < dof; ++c) {
329063a3b9bcSJacob 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);
3291552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3292552f7358SJed Brown     }
3293db485b19SStefano Zampini   } else {
3294db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3295db485b19SStefano Zampini   }
32963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3297552f7358SJed Brown }
3298552f7358SJed Brown 
3299552f7358SJed Brown /*@C
3300eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3301552f7358SJed Brown 
3302a1cb98faSBarry Smith   Not Collective
3303552f7358SJed Brown 
3304552f7358SJed Brown   Input Parameters:
330560225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3306a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3307552f7358SJed Brown 
3308552f7358SJed Brown   Output Parameter:
330920f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3310b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3311552f7358SJed Brown 
3312552f7358SJed Brown   Level: beginner
3313552f7358SJed Brown 
3314a1cb98faSBarry Smith   Note:
3315b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3316b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3317a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3318b5a892a1SMatthew G. Knepley   with the identity.
3319b5a892a1SMatthew G. Knepley 
332060225df5SJacob Faibussowitsch   Fortran Notes:
3321a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3322a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
33233813dfbdSMatthew G Knepley 
33241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3325552f7358SJed Brown @*/
3326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3327d71ae5a4SJacob Faibussowitsch {
3328552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3329552f7358SJed Brown   PetscInt off;
3330552f7358SJed Brown 
3331552f7358SJed Brown   PetscFunctionBegin;
3332552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3334552f7358SJed Brown     PetscInt dof;
33359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33364f572ea9SToby Isaac     if (dof) PetscAssertPointer(coneOrientation, 3);
3337552f7358SJed Brown   }
33389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33390d644c17SKarl Rupp 
3340552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
33413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3342552f7358SJed Brown }
3343552f7358SJed Brown 
3344552f7358SJed Brown /*@
3345eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3346552f7358SJed Brown 
3347a1cb98faSBarry Smith   Not Collective
3348552f7358SJed Brown 
3349552f7358SJed Brown   Input Parameters:
335060225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3351a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
3352b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3353b5a892a1SMatthew G. Knepley 
3354552f7358SJed Brown   Level: beginner
3355552f7358SJed Brown 
3356a1cb98faSBarry Smith   Notes:
3357a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3358a1cb98faSBarry Smith 
3359a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3360a1cb98faSBarry Smith 
33611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3362552f7358SJed Brown @*/
3363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3364d71ae5a4SJacob Faibussowitsch {
3365552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3366552f7358SJed Brown   PetscInt pStart, pEnd;
3367552f7358SJed Brown   PetscInt dof, off, c;
3368552f7358SJed Brown 
3369552f7358SJed Brown   PetscFunctionBegin;
3370552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33724f572ea9SToby Isaac   if (dof) PetscAssertPointer(coneOrientation, 3);
33739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3374db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3375db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
337663a3b9bcSJacob 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);
3377552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3378552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3379552f7358SJed Brown 
33809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
33811dca8a05SBarry 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);
3382552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3383552f7358SJed Brown     }
3384db485b19SStefano Zampini   } else {
3385db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3386db485b19SStefano Zampini   }
33873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3388552f7358SJed Brown }
3389552f7358SJed Brown 
33907cd05799SMatthew G. Knepley /*@
3391eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
33927cd05799SMatthew G. Knepley 
3393a1cb98faSBarry Smith   Not Collective
33947cd05799SMatthew G. Knepley 
33957cd05799SMatthew G. Knepley   Input Parameters:
339660225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
3397a1cb98faSBarry Smith . p         - The point, which must lie in the chart set with `DMPlexSetChart()`
33987cd05799SMatthew G. Knepley . conePos   - The local index in the cone where the point should be put
33997cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
34007cd05799SMatthew G. Knepley 
34017cd05799SMatthew G. Knepley   Level: beginner
34027cd05799SMatthew G. Knepley 
34031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34047cd05799SMatthew G. Knepley @*/
3405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3406d71ae5a4SJacob Faibussowitsch {
3407552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3408552f7358SJed Brown   PetscInt pStart, pEnd;
3409552f7358SJed Brown   PetscInt dof, off;
3410552f7358SJed Brown 
3411552f7358SJed Brown   PetscFunctionBegin;
3412552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3413a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
341563a3b9bcSJacob 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);
341663a3b9bcSJacob 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);
34179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
341863a3b9bcSJacob 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);
3419a03d55ffSStefano Zampini   }
3420a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3421552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
34223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3423552f7358SJed Brown }
3424552f7358SJed Brown 
34257cd05799SMatthew G. Knepley /*@
3426eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
34277cd05799SMatthew G. Knepley 
3428a1cb98faSBarry Smith   Not Collective
34297cd05799SMatthew G. Knepley 
34307cd05799SMatthew G. Knepley   Input Parameters:
343160225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3432a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
34337cd05799SMatthew G. Knepley . conePos         - The local index in the cone where the point should be put
34347cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
34357cd05799SMatthew G. Knepley 
34367cd05799SMatthew G. Knepley   Level: beginner
34377cd05799SMatthew G. Knepley 
3438a1cb98faSBarry Smith   Note:
3439a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3440b5a892a1SMatthew G. Knepley 
34411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34427cd05799SMatthew G. Knepley @*/
3443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3444d71ae5a4SJacob Faibussowitsch {
344577c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
344677c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
344777c88f5bSMatthew G Knepley   PetscInt dof, off;
344877c88f5bSMatthew G Knepley 
344977c88f5bSMatthew G Knepley   PetscFunctionBegin;
345077c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3451a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
345363a3b9bcSJacob 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);
34549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
345563a3b9bcSJacob 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);
3456a03d55ffSStefano Zampini   }
3457a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
345877c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
34593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346077c88f5bSMatthew G Knepley }
346177c88f5bSMatthew G Knepley 
34629f4ada15SMatthew G. Knepley /*@C
34639f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
34649f4ada15SMatthew G. Knepley 
34659f4ada15SMatthew G. Knepley   Not collective
34669f4ada15SMatthew G. Knepley 
34679f4ada15SMatthew G. Knepley   Input Parameters:
34689f4ada15SMatthew G. Knepley + dm - The DMPlex
34699f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
34709f4ada15SMatthew G. Knepley 
34719f4ada15SMatthew G. Knepley   Output Parameters:
347220f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
347320f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
34749f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
34759f4ada15SMatthew G. Knepley 
34769f4ada15SMatthew G. Knepley   Level: beginner
34779f4ada15SMatthew G. Knepley 
34789f4ada15SMatthew G. Knepley   Notes:
34799f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
34809f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
348120f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
34829f4ada15SMatthew G. Knepley   with the identity.
34839f4ada15SMatthew G. Knepley 
34849f4ada15SMatthew G. Knepley   Fortran Notes:
348520f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
348620f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
34879f4ada15SMatthew G. Knepley 
34881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
34899f4ada15SMatthew G. Knepley @*/
34909f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
34919f4ada15SMatthew G. Knepley {
34929f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
34939f4ada15SMatthew G. Knepley 
34949f4ada15SMatthew G. Knepley   PetscFunctionBegin;
34959f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34969f4ada15SMatthew G. Knepley   if (mesh->tr) {
34979f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
34989f4ada15SMatthew G. Knepley   } else {
34999f4ada15SMatthew G. Knepley     PetscInt off;
35009f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
35019f4ada15SMatthew G. Knepley       PetscInt dof;
35029f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
35039f4ada15SMatthew G. Knepley       if (dof) {
35044f572ea9SToby Isaac         if (cone) PetscAssertPointer(cone, 3);
35054f572ea9SToby Isaac         if (ornt) PetscAssertPointer(ornt, 4);
35069f4ada15SMatthew G. Knepley       }
35079f4ada15SMatthew G. Knepley     }
35089f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
35098e3a54c0SPierre Jolivet     if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off);
35108e3a54c0SPierre Jolivet     if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off);
35119f4ada15SMatthew G. Knepley   }
35123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35139f4ada15SMatthew G. Knepley }
35149f4ada15SMatthew G. Knepley 
35159f4ada15SMatthew G. Knepley /*@C
35169f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
35179f4ada15SMatthew G. Knepley 
351820f4b53cSBarry Smith   Not Collective
35199f4ada15SMatthew G. Knepley 
35209f4ada15SMatthew G. Knepley   Input Parameters:
35219f4ada15SMatthew G. Knepley + dm   - The DMPlex
352220f4b53cSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
35239f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
352420f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
35259f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
35269f4ada15SMatthew G. Knepley 
35279f4ada15SMatthew G. Knepley   Level: beginner
35289f4ada15SMatthew G. Knepley 
35299f4ada15SMatthew G. Knepley   Notes:
35309f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
35319f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
353220f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
35339f4ada15SMatthew G. Knepley   with the identity.
35349f4ada15SMatthew G. Knepley 
353560225df5SJacob Faibussowitsch   Fortran Notes:
353620f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
353720f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
35389f4ada15SMatthew G. Knepley 
35391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
35409f4ada15SMatthew G. Knepley @*/
35419f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
35429f4ada15SMatthew G. Knepley {
35439f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
35449f4ada15SMatthew G. Knepley 
35459f4ada15SMatthew G. Knepley   PetscFunctionBegin;
35469f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35479f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
35483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35499f4ada15SMatthew G. Knepley }
35509f4ada15SMatthew G. Knepley 
3551552f7358SJed Brown /*@
3552eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3553552f7358SJed Brown 
3554a1cb98faSBarry Smith   Not Collective
3555552f7358SJed Brown 
3556552f7358SJed Brown   Input Parameters:
355760225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3558a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3559552f7358SJed Brown 
3560552f7358SJed Brown   Output Parameter:
356120f4b53cSBarry Smith . size - The support size for point `p`
3562552f7358SJed Brown 
3563552f7358SJed Brown   Level: beginner
3564552f7358SJed Brown 
35651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3566552f7358SJed Brown @*/
3567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3568d71ae5a4SJacob Faibussowitsch {
3569552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3570552f7358SJed Brown 
3571552f7358SJed Brown   PetscFunctionBegin;
3572552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35734f572ea9SToby Isaac   PetscAssertPointer(size, 3);
35749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
35753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3576552f7358SJed Brown }
3577552f7358SJed Brown 
3578552f7358SJed Brown /*@
3579eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3580552f7358SJed Brown 
3581a1cb98faSBarry Smith   Not Collective
3582552f7358SJed Brown 
3583552f7358SJed Brown   Input Parameters:
358460225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3585a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
358620f4b53cSBarry Smith - size - The support size for point `p`
3587552f7358SJed Brown 
3588a1cb98faSBarry Smith   Level: beginner
3589552f7358SJed Brown 
3590552f7358SJed Brown   Note:
359120f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3592552f7358SJed Brown 
35931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3594552f7358SJed Brown @*/
3595d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3596d71ae5a4SJacob Faibussowitsch {
3597552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3598552f7358SJed Brown 
3599552f7358SJed Brown   PetscFunctionBegin;
3600552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
36023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3603552f7358SJed Brown }
3604552f7358SJed Brown 
3605552f7358SJed Brown /*@C
3606eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3607552f7358SJed Brown 
3608a1cb98faSBarry Smith   Not Collective
3609552f7358SJed Brown 
3610552f7358SJed Brown   Input Parameters:
361160225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3612a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3613552f7358SJed Brown 
3614552f7358SJed Brown   Output Parameter:
361520f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3616552f7358SJed Brown 
3617552f7358SJed Brown   Level: beginner
3618552f7358SJed Brown 
361960225df5SJacob Faibussowitsch   Fortran Notes:
3620a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3621a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
36223813dfbdSMatthew G Knepley 
36231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3624552f7358SJed Brown @*/
3625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3626d71ae5a4SJacob Faibussowitsch {
3627552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3628552f7358SJed Brown   PetscInt off;
3629552f7358SJed Brown 
3630552f7358SJed Brown   PetscFunctionBegin;
3631552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36324f572ea9SToby Isaac   PetscAssertPointer(support, 3);
36339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
36348e3a54c0SPierre Jolivet   *support = PetscSafePointerPlusOffset(mesh->supports, off);
36353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3636552f7358SJed Brown }
3637552f7358SJed Brown 
3638552f7358SJed Brown /*@
363992371b87SBarry 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
3640552f7358SJed Brown 
3641a1cb98faSBarry Smith   Not Collective
3642552f7358SJed Brown 
3643552f7358SJed Brown   Input Parameters:
364460225df5SJacob Faibussowitsch + dm      - The `DMPLEX`
3645a1cb98faSBarry Smith . p       - The point, which must lie in the chart set with `DMPlexSetChart()`
364620f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3647552f7358SJed Brown 
3648552f7358SJed Brown   Level: beginner
3649552f7358SJed Brown 
3650a1cb98faSBarry Smith   Note:
3651a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3652a1cb98faSBarry Smith 
36531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3654552f7358SJed Brown @*/
3655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3656d71ae5a4SJacob Faibussowitsch {
3657552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3658552f7358SJed Brown   PetscInt pStart, pEnd;
3659552f7358SJed Brown   PetscInt dof, off, c;
3660552f7358SJed Brown 
3661552f7358SJed Brown   PetscFunctionBegin;
3662552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
36654f572ea9SToby Isaac   if (dof) PetscAssertPointer(support, 3);
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);
3668552f7358SJed Brown   for (c = 0; c < dof; ++c) {
366963a3b9bcSJacob 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);
3670552f7358SJed Brown     mesh->supports[off + c] = support[c];
3671552f7358SJed Brown   }
36723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3673552f7358SJed Brown }
3674552f7358SJed Brown 
36757cd05799SMatthew G. Knepley /*@
3676eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
36777cd05799SMatthew G. Knepley 
3678a1cb98faSBarry Smith   Not Collective
36797cd05799SMatthew G. Knepley 
36807cd05799SMatthew G. Knepley   Input Parameters:
368160225df5SJacob Faibussowitsch + dm           - The `DMPLEX`
3682a1cb98faSBarry Smith . p            - The point, which must lie in the chart set with `DMPlexSetChart()`
36837cd05799SMatthew G. Knepley . supportPos   - The local index in the cone where the point should be put
36847cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
36857cd05799SMatthew G. Knepley 
36867cd05799SMatthew G. Knepley   Level: beginner
36877cd05799SMatthew G. Knepley 
36881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
36897cd05799SMatthew G. Knepley @*/
3690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3691d71ae5a4SJacob Faibussowitsch {
3692552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3693552f7358SJed Brown   PetscInt pStart, pEnd;
3694552f7358SJed Brown   PetscInt dof, off;
3695552f7358SJed Brown 
3696552f7358SJed Brown   PetscFunctionBegin;
3697552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
37009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
370163a3b9bcSJacob 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);
370263a3b9bcSJacob 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);
370363a3b9bcSJacob 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);
3704552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
37053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3706552f7358SJed Brown }
3707552f7358SJed Brown 
3708b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3709d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3710d71ae5a4SJacob Faibussowitsch {
3711b5a892a1SMatthew G. Knepley   switch (ct) {
3712b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3713b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3714b5a892a1SMatthew G. Knepley     break;
3715b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3716b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3717b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3718b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3719b5a892a1SMatthew G. Knepley     break;
3720b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3721b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3722b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3723b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3724b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3725b5a892a1SMatthew G. Knepley     break;
3726d71ae5a4SJacob Faibussowitsch   default:
3727d71ae5a4SJacob Faibussowitsch     return o;
3728b5a892a1SMatthew G. Knepley   }
3729b5a892a1SMatthew G. Knepley   return o;
3730b5a892a1SMatthew G. Knepley }
3731b5a892a1SMatthew G. Knepley 
3732b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3733d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3734d71ae5a4SJacob Faibussowitsch {
3735b5a892a1SMatthew G. Knepley   switch (ct) {
3736b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3737b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3738b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3739b5a892a1SMatthew G. Knepley     break;
3740b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3741b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3742b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3743b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3744b5a892a1SMatthew G. Knepley     break;
3745b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3746b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3747b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3748b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3749b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3750b5a892a1SMatthew G. Knepley     break;
3751d71ae5a4SJacob Faibussowitsch   default:
3752d71ae5a4SJacob Faibussowitsch     return o;
3753b5a892a1SMatthew G. Knepley   }
3754b5a892a1SMatthew G. Knepley   return o;
3755b5a892a1SMatthew G. Knepley }
3756b5a892a1SMatthew G. Knepley 
3757b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3759d71ae5a4SJacob Faibussowitsch {
3760b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3761b5a892a1SMatthew G. Knepley 
3762b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
37639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3764b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3765b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3766b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3767b5a892a1SMatthew G. Knepley 
37689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
37699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
37709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3771b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3772b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3773b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3774b5a892a1SMatthew G. Knepley 
37759566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3776b5a892a1SMatthew G. Knepley       switch (ct) {
3777b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
37789566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37799566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3780b5a892a1SMatthew G. Knepley         break;
3781b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
37829566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37839566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37849566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3785b5a892a1SMatthew G. Knepley         break;
3786b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
37879566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37889566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37899566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
37909566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3791b5a892a1SMatthew G. Knepley         break;
3792d71ae5a4SJacob Faibussowitsch       default:
3793d71ae5a4SJacob Faibussowitsch         break;
3794b5a892a1SMatthew G. Knepley       }
3795b5a892a1SMatthew G. Knepley     }
3796b5a892a1SMatthew G. Knepley   }
37973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3798b5a892a1SMatthew G. Knepley }
3799b5a892a1SMatthew G. Knepley 
380009015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_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) {
380709015e70SStefano Zampini       PetscCall(DMPlexGetConeSize(dm, p, size));
380809015e70SStefano Zampini       PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt));
380909015e70SStefano Zampini     } else {
381009015e70SStefano Zampini       PetscCall(DMPlexGetSupportSize(dm, p, size));
381109015e70SStefano Zampini       PetscCall(DMPlexGetSupport(dm, p, arr));
381209015e70SStefano Zampini     }
381309015e70SStefano Zampini   } else {
381409015e70SStefano Zampini     if (useCone) {
381509015e70SStefano Zampini       const PetscSection s   = mesh->coneSection;
381609015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
381709015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
381809015e70SStefano Zampini 
381909015e70SStefano Zampini       *size = s->atlasDof[ps];
382009015e70SStefano Zampini       *arr  = mesh->cones + off;
382109015e70SStefano Zampini       *ornt = mesh->coneOrientations + off;
382209015e70SStefano Zampini     } else {
382309015e70SStefano Zampini       const PetscSection s   = mesh->supportSection;
382409015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
382509015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
382609015e70SStefano Zampini 
382709015e70SStefano Zampini       *size = s->atlasDof[ps];
382809015e70SStefano Zampini       *arr  = mesh->supports + off;
382909015e70SStefano Zampini     }
383009015e70SStefano Zampini   }
383109015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
383209015e70SStefano Zampini }
383309015e70SStefano Zampini 
383409015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
383509015e70SStefano Zampini {
383609015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
383709015e70SStefano Zampini 
383809015e70SStefano Zampini   PetscFunctionBeginHot;
383909015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
384009015e70SStefano Zampini     if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt));
384109015e70SStefano Zampini   }
384209015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
384309015e70SStefano Zampini }
384409015e70SStefano Zampini 
3845d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3846d71ae5a4SJacob Faibussowitsch {
3847b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3848b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3849b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3850b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3851b5a892a1SMatthew G. Knepley 
3852b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3853b5a892a1SMatthew G. Knepley   if (ornt) {
38549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3855476787b7SMatthew 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;
3856b5a892a1SMatthew G. Knepley   }
3857b5a892a1SMatthew G. Knepley   if (*points) {
3858b5a892a1SMatthew G. Knepley     closure = *points;
3859b5a892a1SMatthew G. Knepley   } else {
3860b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
38619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
38629566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3863b5a892a1SMatthew G. Knepley   }
386409015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3865b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3866b5a892a1SMatthew G. Knepley     closure[off++] = p;
3867b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3868b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3869b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3870b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3871b5a892a1SMatthew G. Knepley     }
3872b5a892a1SMatthew G. Knepley   } else {
387385036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt);
3874b5a892a1SMatthew G. Knepley 
3875b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3876b5a892a1SMatthew G. Knepley     closure[off++] = p;
3877b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3878b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3879b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3880b5a892a1SMatthew G. Knepley 
38819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3882b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3883b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3884b5a892a1SMatthew G. Knepley     }
3885b5a892a1SMatthew G. Knepley   }
388609015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3887b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3888b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3890b5a892a1SMatthew G. Knepley }
3891b5a892a1SMatthew G. Knepley 
3892d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3893d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3894d71ae5a4SJacob Faibussowitsch {
389585036b15SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
3896b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3897b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3898b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3899b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3900b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3901b5a892a1SMatthew G. Knepley 
3902b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
390409015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
39059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3906b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3907b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3908b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39099371c9d4SSatish Balay   if (*points) {
39109371c9d4SSatish Balay     pts = *points;
39119371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3912b5a892a1SMatthew G. Knepley   c        = 0;
3913b5a892a1SMatthew G. Knepley   pts[c++] = point;
3914b5a892a1SMatthew G. Knepley   pts[c++] = o;
39159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
39169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
39179371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39189371c9d4SSatish Balay     pts[c++] = closure[cl];
39199371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39209371c9d4SSatish Balay   }
39219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
39229371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39239371c9d4SSatish Balay     pts[c++] = closure[cl];
39249371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39259371c9d4SSatish Balay   }
39269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3927b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
39289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3929b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3930b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3931b5a892a1SMatthew G. Knepley   }
393209015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
3933b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3934b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3935b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3936b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3937b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3938b5a892a1SMatthew G. Knepley 
39399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
394085036b15SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
394109015e70SStefano Zampini       PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3942b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3943b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3944b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3945b5a892a1SMatthew G. Knepley 
39469371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
39479371c9d4SSatish Balay           if (pts[i] == cp) break;
3948b5a892a1SMatthew G. Knepley         if (i == c) {
39499566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3950b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3951b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3952b5a892a1SMatthew G. Knepley         }
3953b5a892a1SMatthew G. Knepley       }
395409015e70SStefano Zampini       PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3955b5a892a1SMatthew G. Knepley     }
3956b5a892a1SMatthew G. Knepley   }
3957b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3958b5a892a1SMatthew G. Knepley   *points    = pts;
39593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3960b5a892a1SMatthew G. Knepley }
3961b5a892a1SMatthew G. Knepley 
3962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3963d71ae5a4SJacob Faibussowitsch {
3964b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3965b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3966b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3967b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3968b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3969b5a892a1SMatthew G. Knepley 
3970b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3972b5a892a1SMatthew G. Knepley   if (depth == 1) {
39739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
39743ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3975b5a892a1SMatthew G. Knepley   }
39769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3977476787b7SMatthew 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;
3978c306944fSJed Brown   if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
39799566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
39803ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3981b5a892a1SMatthew G. Knepley   }
39829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3983b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3984b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3985b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39869566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
39879371c9d4SSatish Balay   if (*points) {
39889371c9d4SSatish Balay     closure = *points;
39899371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3990b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3991b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3992b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3993b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3994b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3995b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3996b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3997b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3998b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3999b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
400085036b15SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangement(qt, o);
400109015e70SStefano Zampini     const PetscInt      *tmp, *tmpO = NULL;
4002b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
4003b5a892a1SMatthew G. Knepley 
4004b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
400585036b15SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2;
400663a3b9bcSJacob 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);
4007b5a892a1SMatthew G. Knepley     }
400809015e70SStefano Zampini     PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4009b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
4010b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
4011b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
4012b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
40139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
4014b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
4015b5a892a1SMatthew G. Knepley       PetscInt       c;
4016b5a892a1SMatthew G. Knepley 
4017b5a892a1SMatthew G. Knepley       /* Check for duplicate */
4018b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
4019b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
4020b5a892a1SMatthew G. Knepley       }
4021b5a892a1SMatthew G. Knepley       if (c == closureSize) {
4022b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
4023b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
4024b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
4025b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
4026b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
4027b5a892a1SMatthew G. Knepley       }
4028b5a892a1SMatthew G. Knepley     }
402909015e70SStefano Zampini     PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4030b5a892a1SMatthew G. Knepley   }
40319566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
4032b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
4033b5a892a1SMatthew G. Knepley   if (points) *points = closure;
40343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4035b5a892a1SMatthew G. Knepley }
4036b5a892a1SMatthew G. Knepley 
4037552f7358SJed Brown /*@C
4038eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
4039552f7358SJed Brown 
4040a1cb98faSBarry Smith   Not Collective
4041552f7358SJed Brown 
4042552f7358SJed Brown   Input Parameters:
4043a1cb98faSBarry Smith + dm      - The `DMPLEX`
4044b5a892a1SMatthew G. Knepley . p       - The mesh point
4045a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
4046552f7358SJed Brown 
40476b867d5aSJose E. Roman   Input/Output Parameter:
40486b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
404920f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
40506b867d5aSJose E. Roman 
40516b867d5aSJose E. Roman   Output Parameter:
405220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4053552f7358SJed Brown 
4054a1cb98faSBarry Smith   Level: beginner
4055a1cb98faSBarry Smith 
4056552f7358SJed Brown   Note:
405720f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
4058552f7358SJed Brown 
405960225df5SJacob Faibussowitsch   Fortran Notes:
406020f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
40613813dfbdSMatthew G Knepley 
40621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4063552f7358SJed Brown @*/
4064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4065d71ae5a4SJacob Faibussowitsch {
4066b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4067552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40684f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(numPoints, 4);
40694f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 5);
40709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
40713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40729bf0dad6SMatthew G. Knepley }
40739bf0dad6SMatthew G. Knepley 
4074552f7358SJed Brown /*@C
4075eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
4076552f7358SJed Brown 
4077a1cb98faSBarry Smith   Not Collective
4078552f7358SJed Brown 
4079552f7358SJed Brown   Input Parameters:
4080a1cb98faSBarry Smith + dm        - The `DMPLEX`
4081b5a892a1SMatthew G. Knepley . p         - The mesh point
4082a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
408320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4084b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
4085552f7358SJed Brown 
4086a1cb98faSBarry Smith   Level: beginner
4087a1cb98faSBarry Smith 
4088552f7358SJed Brown   Note:
408920f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
4090552f7358SJed Brown 
40911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4092552f7358SJed Brown @*/
4093d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4094d71ae5a4SJacob Faibussowitsch {
4095b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4096552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40974ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
40989566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
40993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4100552f7358SJed Brown }
4101552f7358SJed Brown 
4102552f7358SJed Brown /*@
4103eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
4104552f7358SJed Brown 
4105a1cb98faSBarry Smith   Not Collective
4106552f7358SJed Brown 
4107552f7358SJed Brown   Input Parameter:
410860225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4109552f7358SJed Brown 
4110552f7358SJed Brown   Output Parameters:
4111552f7358SJed Brown + maxConeSize    - The maximum number of in-edges
4112552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
4113552f7358SJed Brown 
4114552f7358SJed Brown   Level: beginner
4115552f7358SJed Brown 
41161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
4117552f7358SJed Brown @*/
4118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
4119d71ae5a4SJacob Faibussowitsch {
4120552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
4121552f7358SJed Brown 
4122552f7358SJed Brown   PetscFunctionBegin;
4123552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41241baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
41251baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
41263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4127552f7358SJed Brown }
4128552f7358SJed Brown 
4129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
4130d71ae5a4SJacob Faibussowitsch {
4131552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
41326302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
4133552f7358SJed Brown 
4134552f7358SJed Brown   PetscFunctionBegin;
4135552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41369566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
41379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
41389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
41399566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
41406302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41416302a7fbSVaclav Hapla   if (maxSupportSize) {
41429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
41439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
41449566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
4145552f7358SJed Brown   }
41463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4147552f7358SJed Brown }
4148552f7358SJed Brown 
4149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
4150d71ae5a4SJacob Faibussowitsch {
4151552f7358SJed Brown   PetscFunctionBegin;
41529566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
4153dd072f5fSMatthew G. Knepley   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm));
4154ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
4155736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
415695602cf2SAlexis Marboeuf     PetscSF sfNatural;
4157f94b4a02SBlaise Bourdin 
41583dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
41599566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
416095602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
4161c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
4162f94b4a02SBlaise Bourdin   }
41633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4164552f7358SJed Brown }
4165552f7358SJed Brown 
4166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
4167d71ae5a4SJacob Faibussowitsch {
41683dcd263cSBlaise Bourdin   PetscInt i = 0;
41692adcc780SMatthew G. Knepley 
41702adcc780SMatthew G. Knepley   PetscFunctionBegin;
41719566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
41729566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
4173c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
41743dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
41753dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
417695602cf2SAlexis Marboeuf       PetscSF sfNatural;
41773dcd263cSBlaise Bourdin 
41783dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
41799566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
4180c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
418195602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
4182c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
41833dcd263cSBlaise Bourdin       break;
41843dcd263cSBlaise Bourdin     }
41853dcd263cSBlaise Bourdin   }
41863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41872adcc780SMatthew G. Knepley }
41882adcc780SMatthew G. Knepley 
4189552f7358SJed Brown /*@
4190eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
4191552f7358SJed Brown 
4192a1cb98faSBarry Smith   Not Collective
4193552f7358SJed Brown 
4194552f7358SJed Brown   Input Parameter:
419560225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4196552f7358SJed Brown 
4197552f7358SJed Brown   Level: beginner
4198552f7358SJed Brown 
4199a1cb98faSBarry Smith   Note:
4200a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
4201a1cb98faSBarry Smith 
42021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
4203552f7358SJed Brown @*/
4204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
4205d71ae5a4SJacob Faibussowitsch {
4206552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4207552f7358SJed Brown   PetscInt *offsets;
4208552f7358SJed Brown   PetscInt  supportSize;
4209552f7358SJed Brown   PetscInt  pStart, pEnd, p;
4210552f7358SJed Brown 
4211552f7358SJed Brown   PetscFunctionBegin;
4212552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
421328b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
42149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
4215552f7358SJed Brown   /* Calculate support sizes */
42169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4217552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4218552f7358SJed Brown     PetscInt dof, off, c;
4219552f7358SJed Brown 
42209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
422248a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4223552f7358SJed Brown   }
42249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4225552f7358SJed Brown   /* Calculate supports */
42269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
42279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
42289566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4229552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4230552f7358SJed Brown     PetscInt dof, off, c;
4231552f7358SJed Brown 
42329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4234552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4235552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4236552f7358SJed Brown       PetscInt       offS;
4237552f7358SJed Brown 
42389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
42390d644c17SKarl Rupp 
4240552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4241552f7358SJed Brown       ++offsets[q];
4242552f7358SJed Brown     }
4243552f7358SJed Brown   }
42449566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
42459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
42463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4247552f7358SJed Brown }
4248552f7358SJed Brown 
4249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4250d71ae5a4SJacob Faibussowitsch {
4251277ea44aSLisandro Dalcin   IS stratumIS;
4252277ea44aSLisandro Dalcin 
4253277ea44aSLisandro Dalcin   PetscFunctionBegin;
42543ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
425576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4256277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4257277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
42589566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4259277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
42609566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
42619371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
42629371c9d4SSatish Balay         overlap = PETSC_TRUE;
42639371c9d4SSatish Balay         break;
42649371c9d4SSatish Balay       }
4265277ea44aSLisandro Dalcin     }
426663a3b9bcSJacob 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);
4267277ea44aSLisandro Dalcin   }
42689566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
42699566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
42709566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
42713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4272277ea44aSLisandro Dalcin }
4273277ea44aSLisandro Dalcin 
4274e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label)
4275e91fa0a1SMatthew G. Knepley {
4276e91fa0a1SMatthew G. Knepley   PetscInt *pMin, *pMax;
4277e91fa0a1SMatthew G. Knepley   PetscInt  pStart, pEnd;
4278e91fa0a1SMatthew G. Knepley   PetscInt  dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT;
4279e91fa0a1SMatthew G. Knepley 
4280e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4281e91fa0a1SMatthew G. Knepley   {
4282e91fa0a1SMatthew G. Knepley     DMLabel label2;
4283e91fa0a1SMatthew G. Knepley 
4284e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellTypeLabel(dm, &label2));
4285e91fa0a1SMatthew G. Knepley     PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view"));
4286e91fa0a1SMatthew G. Knepley   }
4287e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4288e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4289e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4290e91fa0a1SMatthew G. Knepley 
4291e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4292e91fa0a1SMatthew G. Knepley     dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin);
4293e91fa0a1SMatthew G. Knepley     dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax);
4294e91fa0a1SMatthew G. Knepley   }
4295e91fa0a1SMatthew G. Knepley   PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax));
4296e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4297e91fa0a1SMatthew G. Knepley     pMin[d] = PETSC_MAX_INT;
4298e91fa0a1SMatthew G. Knepley     pMax[d] = PETSC_MIN_INT;
4299e91fa0a1SMatthew G. Knepley   }
4300e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4301e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4302e91fa0a1SMatthew G. Knepley     PetscInt       d;
4303e91fa0a1SMatthew G. Knepley 
4304e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4305e91fa0a1SMatthew G. Knepley     d       = DMPolytopeTypeGetDim(ct);
4306e91fa0a1SMatthew G. Knepley     pMin[d] = PetscMin(p, pMin[d]);
4307e91fa0a1SMatthew G. Knepley     pMax[d] = PetscMax(p, pMax[d]);
4308e91fa0a1SMatthew G. Knepley   }
4309e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4310e91fa0a1SMatthew G. Knepley     if (pMin[d] > pMax[d]) continue;
4311e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1));
4312e91fa0a1SMatthew G. Knepley   }
4313e91fa0a1SMatthew G. Knepley   PetscCall(PetscFree2(pMin, pMax));
4314e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4315e91fa0a1SMatthew G. Knepley }
4316e91fa0a1SMatthew G. Knepley 
4317e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label)
4318e91fa0a1SMatthew G. Knepley {
4319e91fa0a1SMatthew G. Knepley   PetscInt pStart, pEnd;
4320e91fa0a1SMatthew G. Knepley   PetscInt numRoots = 0, numLeaves = 0;
4321e91fa0a1SMatthew G. Knepley 
4322e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4323e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4324e91fa0a1SMatthew G. Knepley   {
4325e91fa0a1SMatthew G. Knepley     /* Initialize roots and count leaves */
4326e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4327e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4328e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4329e91fa0a1SMatthew G. Knepley 
4330e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4331e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4332e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4333e91fa0a1SMatthew G. Knepley       if (!coneSize && supportSize) {
4334e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4335e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4336e91fa0a1SMatthew G. Knepley         ++numRoots;
4337e91fa0a1SMatthew G. Knepley       } else if (!supportSize && coneSize) {
4338e91fa0a1SMatthew G. Knepley         ++numLeaves;
4339e91fa0a1SMatthew G. Knepley       } else if (!supportSize && !coneSize) {
4340e91fa0a1SMatthew G. Knepley         /* Isolated points */
4341e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4342e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4343e91fa0a1SMatthew G. Knepley       }
4344e91fa0a1SMatthew G. Knepley     }
4345e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4346e91fa0a1SMatthew G. Knepley   }
4347e91fa0a1SMatthew G. Knepley 
4348e91fa0a1SMatthew G. Knepley   if (numRoots + numLeaves == (pEnd - pStart)) {
4349e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4350e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4351e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4352e91fa0a1SMatthew G. Knepley 
4353e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4354e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4355e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4356e91fa0a1SMatthew G. Knepley       if (!supportSize && coneSize) {
4357e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4358e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4359e91fa0a1SMatthew G. Knepley       }
4360e91fa0a1SMatthew G. Knepley     }
4361e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4362e91fa0a1SMatthew G. Knepley   } else {
4363e91fa0a1SMatthew G. Knepley     PetscInt level = 0;
4364e91fa0a1SMatthew G. Knepley     PetscInt qStart, qEnd;
4365e91fa0a1SMatthew G. Knepley 
4366e91fa0a1SMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4367e91fa0a1SMatthew G. Knepley     while (qEnd > qStart) {
4368e91fa0a1SMatthew G. Knepley       PetscInt sMin = PETSC_MAX_INT;
4369e91fa0a1SMatthew G. Knepley       PetscInt sMax = PETSC_MIN_INT;
4370e91fa0a1SMatthew G. Knepley 
4371e91fa0a1SMatthew G. Knepley       for (PetscInt q = qStart; q < qEnd; ++q) {
4372e91fa0a1SMatthew G. Knepley         const PetscInt *support;
4373e91fa0a1SMatthew G. Knepley         PetscInt        supportSize;
4374e91fa0a1SMatthew G. Knepley 
4375e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
4376e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupport(dm, q, &support));
4377e91fa0a1SMatthew G. Knepley         for (PetscInt s = 0; s < supportSize; ++s) {
4378e91fa0a1SMatthew G. Knepley           sMin = PetscMin(support[s], sMin);
4379e91fa0a1SMatthew G. Knepley           sMax = PetscMax(support[s], sMax);
4380e91fa0a1SMatthew G. Knepley         }
4381e91fa0a1SMatthew G. Knepley       }
4382e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetNumValues(label, &level));
4383e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
4384e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4385e91fa0a1SMatthew G. Knepley     }
4386e91fa0a1SMatthew G. Knepley   }
4387e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4388e91fa0a1SMatthew G. Knepley }
4389e91fa0a1SMatthew G. Knepley 
4390552f7358SJed Brown /*@
4391a4e35b19SJacob Faibussowitsch   DMPlexStratify - Computes the strata for all points in the `DMPLEX`
4392552f7358SJed Brown 
439320f4b53cSBarry Smith   Collective
4394552f7358SJed Brown 
4395552f7358SJed Brown   Input Parameter:
439660225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4397552f7358SJed Brown 
4398a1cb98faSBarry Smith   Level: beginner
4399552f7358SJed Brown 
4400552f7358SJed Brown   Notes:
4401a4e35b19SJacob Faibussowitsch   The strata group all points of the same grade, and this function calculates the strata. This
4402a4e35b19SJacob Faibussowitsch   grade can be seen as the height (or depth) of the point in the DAG.
4403a4e35b19SJacob Faibussowitsch 
4404a4e35b19SJacob Faibussowitsch   The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
4405a4e35b19SJacob Faibussowitsch   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram).
4406a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4407b1bb481bSMatthew 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
4408a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4409a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4410a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4411552f7358SJed Brown 
4412b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4413b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4414b1bb481bSMatthew 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
4415b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4416a1cb98faSBarry Smith .vb
4417a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4418a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4419a1cb98faSBarry Smith .ve
4420a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4421a1cb98faSBarry Smith .vb
4422a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4423a1cb98faSBarry Smith    depth 1 = {e0, c0}
4424a1cb98faSBarry Smith .ve
4425b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4426b1bb481bSMatthew Knepley 
4427a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4428552f7358SJed Brown 
44291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4430552f7358SJed Brown @*/
4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4432d71ae5a4SJacob Faibussowitsch {
4433df0420ecSMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
4434aa50250dSMatthew G. Knepley   DMLabel   label;
4435e91fa0a1SMatthew G. Knepley   PetscBool flg = PETSC_FALSE;
4436552f7358SJed Brown 
4437552f7358SJed Brown   PetscFunctionBegin;
4438552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4440277ea44aSLisandro Dalcin 
4441e91fa0a1SMatthew G. Knepley   // Create depth label
44429566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
44439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4444277ea44aSLisandro Dalcin 
4445e91fa0a1SMatthew G. Knepley   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL));
4446e91fa0a1SMatthew G. Knepley   if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label));
4447e91fa0a1SMatthew G. Knepley   else PetscCall(DMPlexStratify_Topological_Private(dm, label));
4448552f7358SJed Brown 
4449bf4602e4SToby Isaac   { /* just in case there is an empty process */
4450bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4451bf4602e4SToby Isaac 
44529566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4453712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
445448a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4455bf4602e4SToby Isaac   }
44569566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
44579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
44583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4459552f7358SJed Brown }
4460552f7358SJed Brown 
4461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4462d71ae5a4SJacob Faibussowitsch {
4463412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4464412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4465ba2698f1SMatthew G. Knepley 
4466412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
44679566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
44689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
44699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4470ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4471ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4472ba2698f1SMatthew G. Knepley     switch (pdepth) {
4473d71ae5a4SJacob Faibussowitsch     case 0:
4474d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4475d71ae5a4SJacob Faibussowitsch       break;
4476ba2698f1SMatthew G. Knepley     case 1:
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;
4484ba2698f1SMatthew G. Knepley       case 4:
4485ba2698f1SMatthew G. Knepley         switch (dim) {
4486d71ae5a4SJacob Faibussowitsch         case 2:
4487d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4488d71ae5a4SJacob Faibussowitsch           break;
4489d71ae5a4SJacob Faibussowitsch         case 3:
4490d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4491d71ae5a4SJacob Faibussowitsch           break;
4492d71ae5a4SJacob Faibussowitsch         default:
4493d71ae5a4SJacob Faibussowitsch           break;
4494ba2698f1SMatthew G. Knepley         }
4495ba2698f1SMatthew G. Knepley         break;
4496d71ae5a4SJacob Faibussowitsch       case 5:
4497d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4498d71ae5a4SJacob Faibussowitsch         break;
4499d71ae5a4SJacob Faibussowitsch       case 6:
4500d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4501d71ae5a4SJacob Faibussowitsch         break;
4502d71ae5a4SJacob Faibussowitsch       case 8:
4503d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4504d71ae5a4SJacob Faibussowitsch         break;
4505d71ae5a4SJacob Faibussowitsch       default:
4506d71ae5a4SJacob Faibussowitsch         break;
4507ba2698f1SMatthew G. Knepley       }
4508ba2698f1SMatthew G. Knepley     }
4509ba2698f1SMatthew G. Knepley   } else {
4510ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4511ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4512ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4513ba2698f1SMatthew G. Knepley       switch (dim) {
4514ba2698f1SMatthew G. Knepley       case 1:
4515ba2698f1SMatthew G. Knepley         switch (coneSize) {
4516d71ae5a4SJacob Faibussowitsch         case 2:
4517d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4518d71ae5a4SJacob Faibussowitsch           break;
4519d71ae5a4SJacob Faibussowitsch         default:
4520d71ae5a4SJacob Faibussowitsch           break;
4521ba2698f1SMatthew G. Knepley         }
4522ba2698f1SMatthew G. Knepley         break;
4523ba2698f1SMatthew G. Knepley       case 2:
4524ba2698f1SMatthew G. Knepley         switch (coneSize) {
4525d71ae5a4SJacob Faibussowitsch         case 3:
4526d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4527d71ae5a4SJacob Faibussowitsch           break;
4528d71ae5a4SJacob Faibussowitsch         case 4:
4529d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4530d71ae5a4SJacob Faibussowitsch           break;
4531d71ae5a4SJacob Faibussowitsch         default:
4532d71ae5a4SJacob Faibussowitsch           break;
4533ba2698f1SMatthew G. Knepley         }
4534ba2698f1SMatthew G. Knepley         break;
4535ba2698f1SMatthew G. Knepley       case 3:
4536ba2698f1SMatthew G. Knepley         switch (coneSize) {
4537d71ae5a4SJacob Faibussowitsch         case 4:
4538d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4539d71ae5a4SJacob Faibussowitsch           break;
45409371c9d4SSatish Balay         case 5: {
4541da9060c4SMatthew G. Knepley           const PetscInt *cone;
4542da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4543da9060c4SMatthew G. Knepley 
45449566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
45459566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4546da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4547d71ae5a4SJacob Faibussowitsch           case 3:
4548d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4549d71ae5a4SJacob Faibussowitsch             break;
4550d71ae5a4SJacob Faibussowitsch           case 4:
4551d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4552d71ae5a4SJacob Faibussowitsch             break;
4553da9060c4SMatthew G. Knepley           }
45549371c9d4SSatish Balay         } break;
4555d71ae5a4SJacob Faibussowitsch         case 6:
4556d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4557d71ae5a4SJacob Faibussowitsch           break;
4558d71ae5a4SJacob Faibussowitsch         default:
4559d71ae5a4SJacob Faibussowitsch           break;
4560ba2698f1SMatthew G. Knepley         }
4561ba2698f1SMatthew G. Knepley         break;
4562d71ae5a4SJacob Faibussowitsch       default:
4563d71ae5a4SJacob Faibussowitsch         break;
4564ba2698f1SMatthew G. Knepley       }
4565ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4566ba2698f1SMatthew G. Knepley       switch (coneSize) {
4567d71ae5a4SJacob Faibussowitsch       case 2:
4568d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4569d71ae5a4SJacob Faibussowitsch         break;
4570d71ae5a4SJacob Faibussowitsch       case 3:
4571d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4572d71ae5a4SJacob Faibussowitsch         break;
4573d71ae5a4SJacob Faibussowitsch       case 4:
4574d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4575d71ae5a4SJacob Faibussowitsch         break;
4576d71ae5a4SJacob Faibussowitsch       default:
4577d71ae5a4SJacob Faibussowitsch         break;
4578ba2698f1SMatthew G. Knepley       }
4579ba2698f1SMatthew G. Knepley     }
4580ba2698f1SMatthew G. Knepley   }
4581412e9a14SMatthew G. Knepley   *pt = ct;
45823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4583ba2698f1SMatthew G. Knepley }
4584412e9a14SMatthew G. Knepley 
4585412e9a14SMatthew G. Knepley /*@
4586412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4587412e9a14SMatthew G. Knepley 
458820f4b53cSBarry Smith   Collective
4589412e9a14SMatthew G. Knepley 
4590412e9a14SMatthew G. Knepley   Input Parameter:
459160225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4592412e9a14SMatthew G. Knepley 
4593412e9a14SMatthew G. Knepley   Level: developer
4594412e9a14SMatthew G. Knepley 
4595a1cb98faSBarry Smith   Note:
4596a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4597a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4598a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4599412e9a14SMatthew G. Knepley 
4600a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4601a1cb98faSBarry Smith 
46021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4603412e9a14SMatthew G. Knepley @*/
4604d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4605d71ae5a4SJacob Faibussowitsch {
4606412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4607412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4608412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4609412e9a14SMatthew G. Knepley 
4610412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4611412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4612412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
46139566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
46149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
46159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
461621027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
461721027e53SStefano Zampini   PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
4618412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4619327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4620412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4621412e9a14SMatthew G. Knepley 
46229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
46239566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
4624476787b7SMatthew 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);
46259566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
462621027e53SStefano Zampini     mesh->cellTypes[p - pStart].value_as_uint8 = ct;
4627412e9a14SMatthew G. Knepley   }
46289566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
46299566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
46303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4631ba2698f1SMatthew G. Knepley }
4632ba2698f1SMatthew G. Knepley 
4633552f7358SJed Brown /*@C
4634552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4635552f7358SJed Brown 
4636552f7358SJed Brown   Not Collective
4637552f7358SJed Brown 
4638552f7358SJed Brown   Input Parameters:
4639a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4640552f7358SJed Brown . numPoints - The number of input points for the join
4641552f7358SJed Brown - points    - The input points
4642552f7358SJed Brown 
4643552f7358SJed Brown   Output Parameters:
4644552f7358SJed Brown + numCoveredPoints - The number of points in the join
4645552f7358SJed Brown - coveredPoints    - The points in the join
4646552f7358SJed Brown 
4647552f7358SJed Brown   Level: intermediate
4648552f7358SJed Brown 
4649a1cb98faSBarry Smith   Note:
4650a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4651552f7358SJed Brown 
465260225df5SJacob Faibussowitsch   Fortran Notes:
465320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46543813dfbdSMatthew G Knepley 
46551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4656552f7358SJed Brown @*/
4657d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4658d71ae5a4SJacob Faibussowitsch {
4659552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4660552f7358SJed Brown   PetscInt *join[2];
4661552f7358SJed Brown   PetscInt  joinSize, i = 0;
4662552f7358SJed Brown   PetscInt  dof, off, p, c, m;
46636302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4664552f7358SJed Brown 
4665552f7358SJed Brown   PetscFunctionBegin;
4666552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46674f572ea9SToby Isaac   PetscAssertPointer(points, 3);
46684f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
46694f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
46706302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
46716302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
46726302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4673552f7358SJed Brown   /* Copy in support of first point */
46749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
46759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4676ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4677552f7358SJed Brown   /* Check each successive support */
4678552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4679552f7358SJed Brown     PetscInt newJoinSize = 0;
4680552f7358SJed Brown 
46819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
46829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4683552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4684552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4685552f7358SJed Brown 
4686552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4687552f7358SJed Brown         if (point == join[i][m]) {
4688552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4689552f7358SJed Brown           break;
4690552f7358SJed Brown         }
4691552f7358SJed Brown       }
4692552f7358SJed Brown     }
4693552f7358SJed Brown     joinSize = newJoinSize;
4694552f7358SJed Brown     i        = 1 - i;
4695552f7358SJed Brown   }
4696552f7358SJed Brown   *numCoveredPoints = joinSize;
4697552f7358SJed Brown   *coveredPoints    = join[i];
46986302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
46993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4700552f7358SJed Brown }
4701552f7358SJed Brown 
4702552f7358SJed Brown /*@C
4703552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4704552f7358SJed Brown 
4705552f7358SJed Brown   Not Collective
4706552f7358SJed Brown 
4707552f7358SJed Brown   Input Parameters:
4708a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4709552f7358SJed Brown . numPoints - The number of input points for the join
4710552f7358SJed Brown - points    - The input points
4711552f7358SJed Brown 
4712552f7358SJed Brown   Output Parameters:
4713552f7358SJed Brown + numCoveredPoints - The number of points in the join
4714552f7358SJed Brown - coveredPoints    - The points in the join
4715552f7358SJed Brown 
4716552f7358SJed Brown   Level: intermediate
4717552f7358SJed Brown 
471860225df5SJacob Faibussowitsch   Fortran Notes:
471920f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4720a1cb98faSBarry Smith 
47211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4722552f7358SJed Brown @*/
4723d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4724d71ae5a4SJacob Faibussowitsch {
4725552f7358SJed Brown   PetscFunctionBegin;
4726552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47274f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
47284f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
47294f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
47309566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4731d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
47323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4733552f7358SJed Brown }
4734552f7358SJed Brown 
4735552f7358SJed Brown /*@C
4736552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4737552f7358SJed Brown 
4738552f7358SJed Brown   Not Collective
4739552f7358SJed Brown 
4740552f7358SJed Brown   Input Parameters:
4741a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4742552f7358SJed Brown . numPoints - The number of input points for the join
4743552f7358SJed Brown - points    - The input points
4744552f7358SJed Brown 
4745552f7358SJed Brown   Output Parameters:
4746552f7358SJed Brown + numCoveredPoints - The number of points in the join
4747552f7358SJed Brown - coveredPoints    - The points in the join
4748552f7358SJed Brown 
4749552f7358SJed Brown   Level: intermediate
4750552f7358SJed Brown 
475160225df5SJacob Faibussowitsch   Fortran Notes:
475220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4753a1cb98faSBarry Smith 
47541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4755552f7358SJed Brown @*/
4756d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4757d71ae5a4SJacob Faibussowitsch {
4758552f7358SJed Brown   PetscInt *offsets, **closures;
4759552f7358SJed Brown   PetscInt *join[2];
4760552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
476124c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4762552f7358SJed Brown 
4763552f7358SJed Brown   PetscFunctionBegin;
4764552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47654f572ea9SToby Isaac   PetscAssertPointer(points, 3);
47664f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
47674f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4768552f7358SJed Brown 
47699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
47709566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
47719566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
47726302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
477324c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
47749566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
47759566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4776552f7358SJed Brown 
4777552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4778552f7358SJed Brown     PetscInt closureSize;
4779552f7358SJed Brown 
47809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
47810d644c17SKarl Rupp 
4782552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4783552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4784552f7358SJed Brown       PetscInt pStart, pEnd, i;
4785552f7358SJed Brown 
47869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4787552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4788552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4789552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4790552f7358SJed Brown           break;
4791552f7358SJed Brown         }
4792552f7358SJed Brown       }
4793552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4794552f7358SJed Brown     }
479563a3b9bcSJacob 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);
4796552f7358SJed Brown   }
4797552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4798552f7358SJed Brown     PetscInt dof;
4799552f7358SJed Brown 
4800552f7358SJed Brown     /* Copy in support of first point */
4801552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4802ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4803552f7358SJed Brown     /* Check each successive cone */
4804552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4805552f7358SJed Brown       PetscInt newJoinSize = 0;
4806552f7358SJed Brown 
4807552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4808552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4809552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4810552f7358SJed Brown 
4811552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4812552f7358SJed Brown           if (point == join[i][m]) {
4813552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4814552f7358SJed Brown             break;
4815552f7358SJed Brown           }
4816552f7358SJed Brown         }
4817552f7358SJed Brown       }
4818552f7358SJed Brown       joinSize = newJoinSize;
4819552f7358SJed Brown       i        = 1 - i;
4820552f7358SJed Brown     }
4821552f7358SJed Brown     if (joinSize) break;
4822552f7358SJed Brown   }
4823552f7358SJed Brown   *numCoveredPoints = joinSize;
4824552f7358SJed Brown   *coveredPoints    = join[i];
482548a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
48269566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
48279566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
48286302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
48293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4830552f7358SJed Brown }
4831552f7358SJed Brown 
4832552f7358SJed Brown /*@C
4833552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4834552f7358SJed Brown 
4835552f7358SJed Brown   Not Collective
4836552f7358SJed Brown 
4837552f7358SJed Brown   Input Parameters:
4838a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4839552f7358SJed Brown . numPoints - The number of input points for the meet
4840552f7358SJed Brown - points    - The input points
4841552f7358SJed Brown 
4842552f7358SJed Brown   Output Parameters:
484360225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet
484460225df5SJacob Faibussowitsch - coveringPoints    - The points in the meet
4845552f7358SJed Brown 
4846552f7358SJed Brown   Level: intermediate
4847552f7358SJed Brown 
4848a1cb98faSBarry Smith   Note:
4849a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4850552f7358SJed Brown 
48513813dfbdSMatthew G Knepley   Fortran Notes:
485220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
48533813dfbdSMatthew G Knepley 
48541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4855552f7358SJed Brown @*/
4856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4857d71ae5a4SJacob Faibussowitsch {
4858552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4859552f7358SJed Brown   PetscInt *meet[2];
4860552f7358SJed Brown   PetscInt  meetSize, i = 0;
4861552f7358SJed Brown   PetscInt  dof, off, p, c, m;
48626302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4863552f7358SJed Brown 
4864552f7358SJed Brown   PetscFunctionBegin;
4865552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48664f572ea9SToby Isaac   PetscAssertPointer(points, 3);
48674f572ea9SToby Isaac   PetscAssertPointer(numCoveringPoints, 4);
48684f572ea9SToby Isaac   PetscAssertPointer(coveringPoints, 5);
48696302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
48706302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
48716302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4872552f7358SJed Brown   /* Copy in cone of first point */
48739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
48749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4875ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4876552f7358SJed Brown   /* Check each successive cone */
4877552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4878552f7358SJed Brown     PetscInt newMeetSize = 0;
4879552f7358SJed Brown 
48809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
48819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4882552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4883552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4884552f7358SJed Brown 
4885552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4886552f7358SJed Brown         if (point == meet[i][m]) {
4887552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4888552f7358SJed Brown           break;
4889552f7358SJed Brown         }
4890552f7358SJed Brown       }
4891552f7358SJed Brown     }
4892552f7358SJed Brown     meetSize = newMeetSize;
4893552f7358SJed Brown     i        = 1 - i;
4894552f7358SJed Brown   }
4895552f7358SJed Brown   *numCoveringPoints = meetSize;
4896552f7358SJed Brown   *coveringPoints    = meet[i];
48976302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
48983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4899552f7358SJed Brown }
4900552f7358SJed Brown 
4901552f7358SJed Brown /*@C
4902552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4903552f7358SJed Brown 
4904552f7358SJed Brown   Not Collective
4905552f7358SJed Brown 
4906552f7358SJed Brown   Input Parameters:
4907a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4908552f7358SJed Brown . numPoints - The number of input points for the meet
4909552f7358SJed Brown - points    - The input points
4910552f7358SJed Brown 
4911552f7358SJed Brown   Output Parameters:
4912552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4913552f7358SJed Brown - coveredPoints    - The points in the meet
4914552f7358SJed Brown 
4915552f7358SJed Brown   Level: intermediate
4916552f7358SJed Brown 
491760225df5SJacob Faibussowitsch   Fortran Notes:
491820f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
49193813dfbdSMatthew G Knepley 
49201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4921552f7358SJed Brown @*/
4922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4923d71ae5a4SJacob Faibussowitsch {
4924552f7358SJed Brown   PetscFunctionBegin;
4925552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49264f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
49274f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
49284f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
49299566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4930d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
49313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4932552f7358SJed Brown }
4933552f7358SJed Brown 
4934552f7358SJed Brown /*@C
4935552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4936552f7358SJed Brown 
4937552f7358SJed Brown   Not Collective
4938552f7358SJed Brown 
4939552f7358SJed Brown   Input Parameters:
4940a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4941552f7358SJed Brown . numPoints - The number of input points for the meet
4942552f7358SJed Brown - points    - The input points
4943552f7358SJed Brown 
4944552f7358SJed Brown   Output Parameters:
4945552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4946552f7358SJed Brown - coveredPoints    - The points in the meet
4947552f7358SJed Brown 
4948552f7358SJed Brown   Level: intermediate
4949552f7358SJed Brown 
495060225df5SJacob Faibussowitsch   Fortran Notes:
495120f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
49523813dfbdSMatthew G Knepley 
49531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4954552f7358SJed Brown @*/
4955d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4956d71ae5a4SJacob Faibussowitsch {
4957552f7358SJed Brown   PetscInt *offsets, **closures;
4958552f7358SJed Brown   PetscInt *meet[2];
4959552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
496024c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4961552f7358SJed Brown 
4962552f7358SJed Brown   PetscFunctionBegin;
4963552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49644f572ea9SToby Isaac   PetscAssertPointer(points, 3);
49654f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
49664f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4967552f7358SJed Brown 
49689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
49699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
49709566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
49716302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
497224c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
49739566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
49749566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4975552f7358SJed Brown 
4976552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4977552f7358SJed Brown     PetscInt closureSize;
4978552f7358SJed Brown 
49799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
49800d644c17SKarl Rupp 
4981552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4982552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4983552f7358SJed Brown       PetscInt pStart, pEnd, i;
4984552f7358SJed Brown 
49859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4986552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4987552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4988552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4989552f7358SJed Brown           break;
4990552f7358SJed Brown         }
4991552f7358SJed Brown       }
4992552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4993552f7358SJed Brown     }
499463a3b9bcSJacob 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);
4995552f7358SJed Brown   }
4996552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4997552f7358SJed Brown     PetscInt dof;
4998552f7358SJed Brown 
4999552f7358SJed Brown     /* Copy in cone of first point */
5000552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
5001ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
5002552f7358SJed Brown     /* Check each successive cone */
5003552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
5004552f7358SJed Brown       PetscInt newMeetSize = 0;
5005552f7358SJed Brown 
5006552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
5007552f7358SJed Brown       for (c = 0; c < dof; ++c) {
5008552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
5009552f7358SJed Brown 
5010552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
5011552f7358SJed Brown           if (point == meet[i][m]) {
5012552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
5013552f7358SJed Brown             break;
5014552f7358SJed Brown           }
5015552f7358SJed Brown         }
5016552f7358SJed Brown       }
5017552f7358SJed Brown       meetSize = newMeetSize;
5018552f7358SJed Brown       i        = 1 - i;
5019552f7358SJed Brown     }
5020552f7358SJed Brown     if (meetSize) break;
5021552f7358SJed Brown   }
5022552f7358SJed Brown   *numCoveredPoints = meetSize;
5023552f7358SJed Brown   *coveredPoints    = meet[i];
502448a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
50259566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
50269566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
50276302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
50283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5029552f7358SJed Brown }
5030552f7358SJed Brown 
50314e3744c5SMatthew G. Knepley /*@C
5032a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
50334e3744c5SMatthew G. Knepley 
50344e3744c5SMatthew G. Knepley   Not Collective
50354e3744c5SMatthew G. Knepley 
50364e3744c5SMatthew G. Knepley   Input Parameters:
5037a1cb98faSBarry Smith + dmA - A `DMPLEX` object
5038a1cb98faSBarry Smith - dmB - A `DMPLEX` object
50394e3744c5SMatthew G. Knepley 
50402fe279fdSBarry Smith   Output Parameter:
5041a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
50424e3744c5SMatthew G. Knepley 
50434e3744c5SMatthew G. Knepley   Level: intermediate
50444e3744c5SMatthew G. Knepley 
5045a1cb98faSBarry Smith   Note:
50463c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
50474e3744c5SMatthew G. Knepley 
50481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
50494e3744c5SMatthew G. Knepley @*/
5050d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
5051d71ae5a4SJacob Faibussowitsch {
50524e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
50534e3744c5SMatthew G. Knepley 
50544e3744c5SMatthew G. Knepley   PetscFunctionBegin;
50554e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
50564e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
50574f572ea9SToby Isaac   PetscAssertPointer(equal, 3);
50584e3744c5SMatthew G. Knepley 
50594e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
50609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
50619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
50623ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
50639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
50649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
50653ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
50664e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
50674e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
50684e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
50694e3744c5SMatthew G. Knepley 
50709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
50719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
50729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
50739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
50749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
50759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
50763ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
50774e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
50783ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
50793ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
50804e3744c5SMatthew G. Knepley     }
50819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
50829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
50839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
50849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
50853ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
50864e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
50873ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
50884e3744c5SMatthew G. Knepley     }
50894e3744c5SMatthew G. Knepley   }
50904e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
50913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50924e3744c5SMatthew G. Knepley }
50934e3744c5SMatthew G. Knepley 
50947cd05799SMatthew G. Knepley /*@C
50957cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
50967cd05799SMatthew G. Knepley 
50977cd05799SMatthew G. Knepley   Not Collective
50987cd05799SMatthew G. Knepley 
50997cd05799SMatthew G. Knepley   Input Parameters:
5100a1cb98faSBarry Smith + dm         - The `DMPLEX`
51017cd05799SMatthew G. Knepley . cellDim    - The cell dimension
51027cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
51037cd05799SMatthew G. Knepley 
51042fe279fdSBarry Smith   Output Parameter:
51057cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
51067cd05799SMatthew G. Knepley 
51077cd05799SMatthew G. Knepley   Level: developer
51087cd05799SMatthew G. Knepley 
5109a1cb98faSBarry Smith   Note:
51107cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
51117cd05799SMatthew G. Knepley 
51121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
51137cd05799SMatthew G. Knepley @*/
5114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
5115d71ae5a4SJacob Faibussowitsch {
511682f516ccSBarry Smith   MPI_Comm comm;
5117552f7358SJed Brown 
5118552f7358SJed Brown   PetscFunctionBegin;
51199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
51204f572ea9SToby Isaac   PetscAssertPointer(numFaceVertices, 4);
5121552f7358SJed Brown   switch (cellDim) {
5122d71ae5a4SJacob Faibussowitsch   case 0:
5123d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
5124d71ae5a4SJacob Faibussowitsch     break;
5125d71ae5a4SJacob Faibussowitsch   case 1:
5126d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
5127d71ae5a4SJacob Faibussowitsch     break;
5128552f7358SJed Brown   case 2:
5129552f7358SJed Brown     switch (numCorners) {
513019436ca2SJed Brown     case 3:                 /* triangle */
513119436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5132552f7358SJed Brown       break;
513319436ca2SJed Brown     case 4:                 /* quadrilateral */
513419436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5135552f7358SJed Brown       break;
513619436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
513719436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5138552f7358SJed Brown       break;
513919436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
514019436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5141552f7358SJed Brown       break;
5142d71ae5a4SJacob Faibussowitsch     default:
5143d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5144552f7358SJed Brown     }
5145552f7358SJed Brown     break;
5146552f7358SJed Brown   case 3:
5147552f7358SJed Brown     switch (numCorners) {
514819436ca2SJed Brown     case 4:                 /* tetradehdron */
514919436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
5150552f7358SJed Brown       break;
515119436ca2SJed Brown     case 6:                 /* tet cohesive cells */
515219436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5153552f7358SJed Brown       break;
515419436ca2SJed Brown     case 8:                 /* hexahedron */
515519436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5156552f7358SJed Brown       break;
515719436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
515819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5159552f7358SJed Brown       break;
516019436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
516119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5162552f7358SJed Brown       break;
516319436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
516419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5165552f7358SJed Brown       break;
516619436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
516719436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5168552f7358SJed Brown       break;
516919436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
517019436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
5171552f7358SJed Brown       break;
5172d71ae5a4SJacob Faibussowitsch     default:
5173d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5174552f7358SJed Brown     }
5175552f7358SJed Brown     break;
5176d71ae5a4SJacob Faibussowitsch   default:
5177d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
5178552f7358SJed Brown   }
51793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5180552f7358SJed Brown }
5181552f7358SJed Brown 
5182552f7358SJed Brown /*@
5183a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
5184552f7358SJed Brown 
5185552f7358SJed Brown   Not Collective
5186552f7358SJed Brown 
5187aa50250dSMatthew G. Knepley   Input Parameter:
5188a1cb98faSBarry Smith . dm - The `DMPLEX` object
5189552f7358SJed Brown 
5190aa50250dSMatthew G. Knepley   Output Parameter:
5191a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
5192552f7358SJed Brown 
5193552f7358SJed Brown   Level: developer
5194552f7358SJed Brown 
51951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
5196aa50250dSMatthew G. Knepley @*/
5197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
5198d71ae5a4SJacob Faibussowitsch {
5199aa50250dSMatthew G. Knepley   PetscFunctionBegin;
5200aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52014f572ea9SToby Isaac   PetscAssertPointer(depthLabel, 2);
5202c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
52033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5204aa50250dSMatthew G. Knepley }
5205aa50250dSMatthew G. Knepley 
5206aa50250dSMatthew G. Knepley /*@
5207aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
5208aa50250dSMatthew G. Knepley 
5209aa50250dSMatthew G. Knepley   Not Collective
5210aa50250dSMatthew G. Knepley 
5211aa50250dSMatthew G. Knepley   Input Parameter:
5212a1cb98faSBarry Smith . dm - The `DMPLEX` object
5213aa50250dSMatthew G. Knepley 
5214aa50250dSMatthew G. Knepley   Output Parameter:
5215aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
5216aa50250dSMatthew G. Knepley 
5217aa50250dSMatthew G. Knepley   Level: developer
5218552f7358SJed Brown 
5219b1bb481bSMatthew Knepley   Notes:
5220a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
5221a1cb98faSBarry Smith 
5222a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
5223a1cb98faSBarry Smith 
5224dc287ab2SVaclav Hapla   An empty mesh gives -1.
5225b1bb481bSMatthew Knepley 
52261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
5227552f7358SJed Brown @*/
5228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
5229d71ae5a4SJacob Faibussowitsch {
52309f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5231aa50250dSMatthew G. Knepley   DMLabel  label;
5232aa50250dSMatthew G. Knepley   PetscInt d = 0;
5233552f7358SJed Brown 
5234552f7358SJed Brown   PetscFunctionBegin;
5235552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52364f572ea9SToby Isaac   PetscAssertPointer(depth, 2);
52379f4ada15SMatthew G. Knepley   if (mesh->tr) {
52389f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
52399f4ada15SMatthew G. Knepley   } else {
52409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
52419566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
5242552f7358SJed Brown     *depth = d - 1;
52439f4ada15SMatthew G. Knepley   }
52443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5245552f7358SJed Brown }
5246552f7358SJed Brown 
5247552f7358SJed Brown /*@
524820f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
5249552f7358SJed Brown 
5250552f7358SJed Brown   Not Collective
5251552f7358SJed Brown 
5252552f7358SJed Brown   Input Parameters:
5253a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5254570fa34dSVaclav Hapla - depth - The requested depth
5255552f7358SJed Brown 
5256552f7358SJed Brown   Output Parameters:
525720f4b53cSBarry Smith + start - The first point at this `depth`
525820f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
5259552f7358SJed Brown 
5260552f7358SJed Brown   Level: developer
5261552f7358SJed Brown 
5262a1cb98faSBarry Smith   Notes:
5263a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
5264a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
5265a1cb98faSBarry Smith   higher dimension, e.g., "edges".
5266a1cb98faSBarry Smith 
52672827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
5268552f7358SJed Brown @*/
5269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
5270d71ae5a4SJacob Faibussowitsch {
52719f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5272aa50250dSMatthew G. Knepley   DMLabel  label;
527363d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
5274552f7358SJed Brown 
5275552f7358SJed Brown   PetscFunctionBegin;
5276552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52779371c9d4SSatish Balay   if (start) {
52784f572ea9SToby Isaac     PetscAssertPointer(start, 3);
52799371c9d4SSatish Balay     *start = 0;
52809371c9d4SSatish Balay   }
52819371c9d4SSatish Balay   if (end) {
52824f572ea9SToby Isaac     PetscAssertPointer(end, 4);
52839371c9d4SSatish Balay     *end = 0;
52849371c9d4SSatish Balay   }
52859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
52863ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5287570fa34dSVaclav Hapla   if (depth < 0) {
528863d1a920SMatthew G. Knepley     if (start) *start = pStart;
528963d1a920SMatthew G. Knepley     if (end) *end = pEnd;
52903ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5291552f7358SJed Brown   }
52929f4ada15SMatthew G. Knepley   if (mesh->tr) {
52939f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
52949f4ada15SMatthew G. Knepley   } else {
52959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
529628b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5297570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
52989f4ada15SMatthew G. Knepley   }
52993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5300552f7358SJed Brown }
5301552f7358SJed Brown 
5302552f7358SJed Brown /*@
530320f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5304552f7358SJed Brown 
5305552f7358SJed Brown   Not Collective
5306552f7358SJed Brown 
5307552f7358SJed Brown   Input Parameters:
5308a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5309570fa34dSVaclav Hapla - height - The requested height
5310552f7358SJed Brown 
5311552f7358SJed Brown   Output Parameters:
531220f4b53cSBarry Smith + start - The first point at this `height`
531320f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5314552f7358SJed Brown 
5315552f7358SJed Brown   Level: developer
5316552f7358SJed Brown 
5317a1cb98faSBarry Smith   Notes:
5318a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5319a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5320a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5321a1cb98faSBarry Smith 
53222827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5323552f7358SJed Brown @*/
5324d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5325d71ae5a4SJacob Faibussowitsch {
5326aa50250dSMatthew G. Knepley   DMLabel  label;
532763d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5328552f7358SJed Brown 
5329552f7358SJed Brown   PetscFunctionBegin;
5330552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53319371c9d4SSatish Balay   if (start) {
53324f572ea9SToby Isaac     PetscAssertPointer(start, 3);
53339371c9d4SSatish Balay     *start = 0;
53349371c9d4SSatish Balay   }
53359371c9d4SSatish Balay   if (end) {
53364f572ea9SToby Isaac     PetscAssertPointer(end, 4);
53379371c9d4SSatish Balay     *end = 0;
53389371c9d4SSatish Balay   }
53399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
53403ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5341570fa34dSVaclav Hapla   if (height < 0) {
534263d1a920SMatthew G. Knepley     if (start) *start = pStart;
534363d1a920SMatthew G. Knepley     if (end) *end = pEnd;
53443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5345552f7358SJed Brown   }
53469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
534759e4dc13SStefano Zampini   if (label) PetscCall(DMLabelGetNumValues(label, &depth));
534859e4dc13SStefano Zampini   else PetscCall(DMGetDimension(dm, &depth));
534959e4dc13SStefano Zampini   PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed");
535059e4dc13SStefano Zampini   PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end));
53513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5352552f7358SJed Brown }
5353552f7358SJed Brown 
5354ba2698f1SMatthew G. Knepley /*@
535520f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5356ba2698f1SMatthew G. Knepley 
5357ba2698f1SMatthew G. Knepley   Not Collective
5358ba2698f1SMatthew G. Knepley 
5359d8d19677SJose E. Roman   Input Parameters:
5360a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5361ba2698f1SMatthew G. Knepley - point - The point
5362ba2698f1SMatthew G. Knepley 
5363ba2698f1SMatthew G. Knepley   Output Parameter:
536420f4b53cSBarry Smith . depth - The depth of the `point`
5365ba2698f1SMatthew G. Knepley 
5366ba2698f1SMatthew G. Knepley   Level: intermediate
5367ba2698f1SMatthew G. Knepley 
53681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5369ba2698f1SMatthew G. Knepley @*/
5370d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5371d71ae5a4SJacob Faibussowitsch {
5372ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5373ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53744f572ea9SToby Isaac   PetscAssertPointer(depth, 3);
53759566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
53763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5377ba2698f1SMatthew G. Knepley }
5378ba2698f1SMatthew G. Knepley 
5379ba2698f1SMatthew G. Knepley /*@
538020f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
53810c0a32dcSVaclav Hapla 
53820c0a32dcSVaclav Hapla   Not Collective
53830c0a32dcSVaclav Hapla 
5384d8d19677SJose E. Roman   Input Parameters:
5385a1cb98faSBarry Smith + dm    - The `DMPLEX` object
53860c0a32dcSVaclav Hapla - point - The point
53870c0a32dcSVaclav Hapla 
53880c0a32dcSVaclav Hapla   Output Parameter:
538920f4b53cSBarry Smith . height - The height of the `point`
53900c0a32dcSVaclav Hapla 
53910c0a32dcSVaclav Hapla   Level: intermediate
53920c0a32dcSVaclav Hapla 
53931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
53940c0a32dcSVaclav Hapla @*/
5395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5396d71ae5a4SJacob Faibussowitsch {
53970c0a32dcSVaclav Hapla   PetscInt n, pDepth;
53980c0a32dcSVaclav Hapla 
53990c0a32dcSVaclav Hapla   PetscFunctionBegin;
54000c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54014f572ea9SToby Isaac   PetscAssertPointer(height, 3);
54029566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
54039566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
54040c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
54053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54060c0a32dcSVaclav Hapla }
54070c0a32dcSVaclav Hapla 
54080c0a32dcSVaclav Hapla /*@
5409a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5410ba2698f1SMatthew G. Knepley 
5411ba2698f1SMatthew G. Knepley   Not Collective
5412ba2698f1SMatthew G. Knepley 
5413ba2698f1SMatthew G. Knepley   Input Parameter:
5414a1cb98faSBarry Smith . dm - The `DMPLEX` object
5415ba2698f1SMatthew G. Knepley 
5416ba2698f1SMatthew G. Knepley   Output Parameter:
5417a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5418412e9a14SMatthew G. Knepley 
5419ba2698f1SMatthew G. Knepley   Level: developer
5420ba2698f1SMatthew G. Knepley 
5421a1cb98faSBarry Smith   Note:
5422a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5423a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5424a1cb98faSBarry Smith 
54251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5426ba2698f1SMatthew G. Knepley @*/
5427d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5428d71ae5a4SJacob Faibussowitsch {
5429ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5430ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54314f572ea9SToby Isaac   PetscAssertPointer(celltypeLabel, 2);
54329566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5433ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
54343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5435ba2698f1SMatthew G. Knepley }
5436ba2698f1SMatthew G. Knepley 
5437ba2698f1SMatthew G. Knepley /*@
5438ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5439ba2698f1SMatthew G. Knepley 
5440ba2698f1SMatthew G. Knepley   Not Collective
5441ba2698f1SMatthew G. Knepley 
5442d8d19677SJose E. Roman   Input Parameters:
5443a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5444ba2698f1SMatthew G. Knepley - cell - The cell
5445ba2698f1SMatthew G. Knepley 
5446ba2698f1SMatthew G. Knepley   Output Parameter:
5447ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5448ba2698f1SMatthew G. Knepley 
5449ba2698f1SMatthew G. Knepley   Level: intermediate
5450ba2698f1SMatthew G. Knepley 
54511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5452ba2698f1SMatthew G. Knepley @*/
5453d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5454d71ae5a4SJacob Faibussowitsch {
54559f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5456ba2698f1SMatthew G. Knepley   DMLabel  label;
5457ba2698f1SMatthew G. Knepley   PetscInt ct;
5458ba2698f1SMatthew G. Knepley 
5459ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5460ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54614f572ea9SToby Isaac   PetscAssertPointer(celltype, 3);
54629f4ada15SMatthew G. Knepley   if (mesh->tr) {
54639f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
54649f4ada15SMatthew G. Knepley   } else {
546521027e53SStefano Zampini     PetscInt pStart, pEnd;
546621027e53SStefano Zampini 
546721027e53SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL));
546821027e53SStefano Zampini     if (!mesh->cellTypes) { /* XXX remove? optimize? */
546921027e53SStefano Zampini       PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd));
547021027e53SStefano Zampini       PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
547121027e53SStefano Zampini       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
547221027e53SStefano Zampini       for (PetscInt p = pStart; p < pEnd; p++) {
547321027e53SStefano Zampini         PetscCall(DMLabelGetValue(label, p, &ct));
547421027e53SStefano Zampini         mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct;
547521027e53SStefano Zampini       }
547621027e53SStefano Zampini     }
547721027e53SStefano Zampini     *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8;
547821027e53SStefano Zampini     if (PetscDefined(USE_DEBUG)) {
54799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
54809566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, cell, &ct));
548163a3b9bcSJacob Faibussowitsch       PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5482936381afSPierre Jolivet       PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct);
548321027e53SStefano Zampini     }
54849f4ada15SMatthew G. Knepley   }
54853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5486ba2698f1SMatthew G. Knepley }
5487ba2698f1SMatthew G. Knepley 
5488412e9a14SMatthew G. Knepley /*@
5489412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5490412e9a14SMatthew G. Knepley 
5491412e9a14SMatthew G. Knepley   Not Collective
5492412e9a14SMatthew G. Knepley 
5493412e9a14SMatthew G. Knepley   Input Parameters:
5494a1cb98faSBarry Smith + dm       - The `DMPLEX` object
5495412e9a14SMatthew G. Knepley . cell     - The cell
5496412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5497412e9a14SMatthew G. Knepley 
5498a1cb98faSBarry Smith   Level: advanced
5499a1cb98faSBarry Smith 
5500a1cb98faSBarry Smith   Note:
5501a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5502412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5503412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5504db485b19SStefano Zampini   DMCreateLabel(dm, "celltype") before getting or setting any cell types.
5505412e9a14SMatthew G. Knepley 
55061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5507412e9a14SMatthew G. Knepley @*/
5508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5509d71ae5a4SJacob Faibussowitsch {
551021027e53SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
5511412e9a14SMatthew G. Knepley   DMLabel  label;
551221027e53SStefano Zampini   PetscInt pStart, pEnd;
5513412e9a14SMatthew G. Knepley 
5514412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5515412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
551621027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
55179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
55189566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
551921027e53SStefano Zampini   if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
552021027e53SStefano Zampini   mesh->cellTypes[cell - pStart].value_as_uint8 = celltype;
55213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5522412e9a14SMatthew G. Knepley }
5523412e9a14SMatthew G. Knepley 
5524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5525d71ae5a4SJacob Faibussowitsch {
5526efe440bfSMatthew G. Knepley   PetscSection section, s;
5527efe440bfSMatthew G. Knepley   Mat          m;
55283e922f36SToby Isaac   PetscInt     maxHeight;
5529dd4c3f67SMatthew G. Knepley   const char  *prefix;
5530552f7358SJed Brown 
5531552f7358SJed Brown   PetscFunctionBegin;
55329566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5533dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5534dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5535dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
55369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
55379566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
55389566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
55399566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
55409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
55419566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
55429566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
55439566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
55449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
55459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
55468f4c458bSMatthew G. Knepley 
55479566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
55489566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5549dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5550dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
55513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5552552f7358SJed Brown }
5553552f7358SJed Brown 
5554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5555d71ae5a4SJacob Faibussowitsch {
55566858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
55576858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5558f19dbd58SToby Isaac 
5559f19dbd58SToby Isaac   PetscFunctionBegin;
5560f19dbd58SToby Isaac   *field = NULL;
55619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
55629566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
55636858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
55646858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5565f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
55666858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
55676858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5568f19dbd58SToby Isaac   }
55693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5570f19dbd58SToby Isaac }
5571f19dbd58SToby Isaac 
55727cd05799SMatthew G. Knepley /*@C
55737cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
55747cd05799SMatthew G. Knepley 
55757cd05799SMatthew G. Knepley   Not Collective
55767cd05799SMatthew G. Knepley 
55772fe279fdSBarry Smith   Input Parameter:
5578a1cb98faSBarry Smith . dm - The `DMPLEX` object
55797cd05799SMatthew G. Knepley 
55807cd05799SMatthew G. Knepley   Output Parameter:
5581a1cb98faSBarry Smith . section - The `PetscSection` object
55827cd05799SMatthew G. Knepley 
55837cd05799SMatthew G. Knepley   Level: developer
55847cd05799SMatthew G. Knepley 
55851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
55867cd05799SMatthew G. Knepley @*/
5587d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5588d71ae5a4SJacob Faibussowitsch {
5589552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5590552f7358SJed Brown 
5591552f7358SJed Brown   PetscFunctionBegin;
5592552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5593552f7358SJed Brown   if (section) *section = mesh->coneSection;
55943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5595552f7358SJed Brown }
5596552f7358SJed Brown 
55977cd05799SMatthew G. Knepley /*@C
55987cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
55997cd05799SMatthew G. Knepley 
56007cd05799SMatthew G. Knepley   Not Collective
56017cd05799SMatthew G. Knepley 
56022fe279fdSBarry Smith   Input Parameter:
5603a1cb98faSBarry Smith . dm - The `DMPLEX` object
56047cd05799SMatthew G. Knepley 
56057cd05799SMatthew G. Knepley   Output Parameter:
5606a1cb98faSBarry Smith . section - The `PetscSection` object
56077cd05799SMatthew G. Knepley 
56087cd05799SMatthew G. Knepley   Level: developer
56097cd05799SMatthew G. Knepley 
56101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
56117cd05799SMatthew G. Knepley @*/
5612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5613d71ae5a4SJacob Faibussowitsch {
56148cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
56158cb4d582SMatthew G. Knepley 
56168cb4d582SMatthew G. Knepley   PetscFunctionBegin;
56178cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56188cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
56193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56208cb4d582SMatthew G. Knepley }
56218cb4d582SMatthew G. Knepley 
56227cd05799SMatthew G. Knepley /*@C
56237cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
56247cd05799SMatthew G. Knepley 
56257cd05799SMatthew G. Knepley   Not Collective
56267cd05799SMatthew G. Knepley 
56272fe279fdSBarry Smith   Input Parameter:
5628a1cb98faSBarry Smith . dm - The `DMPLEX` object
56297cd05799SMatthew G. Knepley 
56307cd05799SMatthew G. Knepley   Output Parameter:
56317cd05799SMatthew G. Knepley . cones - The cone for each point
56327cd05799SMatthew G. Knepley 
56337cd05799SMatthew G. Knepley   Level: developer
56347cd05799SMatthew G. Knepley 
56351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
56367cd05799SMatthew G. Knepley @*/
5637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5638d71ae5a4SJacob Faibussowitsch {
5639552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5640552f7358SJed Brown 
5641552f7358SJed Brown   PetscFunctionBegin;
5642552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5643552f7358SJed Brown   if (cones) *cones = mesh->cones;
56443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5645552f7358SJed Brown }
5646552f7358SJed Brown 
56477cd05799SMatthew G. Knepley /*@C
56487cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
56497cd05799SMatthew G. Knepley 
56507cd05799SMatthew G. Knepley   Not Collective
56517cd05799SMatthew G. Knepley 
56522fe279fdSBarry Smith   Input Parameter:
5653a1cb98faSBarry Smith . dm - The `DMPLEX` object
56547cd05799SMatthew G. Knepley 
56557cd05799SMatthew G. Knepley   Output Parameter:
5656b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
56577cd05799SMatthew G. Knepley 
56587cd05799SMatthew G. Knepley   Level: developer
56597cd05799SMatthew G. Knepley 
5660b5a892a1SMatthew G. Knepley   Notes:
5661a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5662b5a892a1SMatthew G. Knepley 
5663a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5664b5a892a1SMatthew G. Knepley 
56651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
56667cd05799SMatthew G. Knepley @*/
5667d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5668d71ae5a4SJacob Faibussowitsch {
5669552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5670552f7358SJed Brown 
5671552f7358SJed Brown   PetscFunctionBegin;
5672552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5673552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
56743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5675552f7358SJed Brown }
5676552f7358SJed Brown 
5677552f7358SJed Brown /******************************** FEM Support **********************************/
5678552f7358SJed Brown 
5679d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
5680d2b2dc1eSMatthew G. Knepley {
5681d2b2dc1eSMatthew G. Knepley   PetscInt depth;
5682d2b2dc1eSMatthew G. Knepley 
5683d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
5684d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
5685d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS));
5686d2b2dc1eSMatthew G. Knepley   if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS));
5687d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5688d2b2dc1eSMatthew G. Knepley }
5689d2b2dc1eSMatthew G. Knepley 
56905962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS)
56915962854dSMatthew G. Knepley {
56925962854dSMatthew G. Knepley   PetscInt depth;
56935962854dSMatthew G. Knepley 
56945962854dSMatthew G. Knepley   PetscFunctionBegin;
56955962854dSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
56965962854dSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS));
56975962854dSMatthew G. Knepley   if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS));
56985962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
56995962854dSMatthew G. Knepley }
57005962854dSMatthew G. Knepley 
57019e8305c2SJed Brown /*
57029e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
57039e8305c2SJed Brown  representing a line in the section.
57049e8305c2SJed Brown */
57055f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor)
5706d71ae5a4SJacob Faibussowitsch {
5707e327e467SRezgar Shakeri   PetscObject  obj;
5708e327e467SRezgar Shakeri   PetscClassId id;
5709e327e467SRezgar Shakeri   PetscFE      fe = NULL;
5710e327e467SRezgar Shakeri 
57119e8305c2SJed Brown   PetscFunctionBeginHot;
57129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5713e327e467SRezgar Shakeri   PetscCall(DMGetField(dm, field, NULL, &obj));
5714e327e467SRezgar Shakeri   PetscCall(PetscObjectGetClassId(obj, &id));
5715e327e467SRezgar Shakeri   if (id == PETSCFE_CLASSID) fe = (PetscFE)obj;
5716e327e467SRezgar Shakeri 
5717e327e467SRezgar Shakeri   if (!fe) {
5718e327e467SRezgar Shakeri     /* Assume the full interpolated mesh is in the chart; lines in particular */
57199e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
57209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
57219e8305c2SJed Brown     *k = *k / *Nc + 1;
5722e327e467SRezgar Shakeri   } else {
5723e327e467SRezgar Shakeri     PetscInt       dual_space_size, dim;
57245f82726aSMatthew G. Knepley     PetscDualSpace dsp;
57255f82726aSMatthew G. Knepley 
5726e327e467SRezgar Shakeri     PetscCall(DMGetDimension(dm, &dim));
57275f82726aSMatthew G. Knepley     PetscCall(PetscFEGetDualSpace(fe, &dsp));
57285f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size));
5729e327e467SRezgar Shakeri     *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1;
57305f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous));
57315f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor));
57325f82726aSMatthew G. Knepley   }
57335f82726aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
57345f82726aSMatthew G. Knepley }
57355f82726aSMatthew G. Knepley 
57365f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof)
57375f82726aSMatthew G. Knepley {
57385f82726aSMatthew G. Knepley   PetscFunctionBeginHot;
57395f82726aSMatthew G. Knepley   if (tensor) {
57405f82726aSMatthew G. Knepley     *dof = PetscPowInt(k + 1, dim);
57415f82726aSMatthew G. Knepley   } else {
57425f82726aSMatthew G. Knepley     switch (dim) {
57435f82726aSMatthew G. Knepley     case 1:
57445f82726aSMatthew G. Knepley       *dof = k + 1;
57455f82726aSMatthew G. Knepley       break;
57465f82726aSMatthew G. Knepley     case 2:
57475f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2)) / 2;
57485f82726aSMatthew G. Knepley       break;
57495f82726aSMatthew G. Knepley     case 3:
57505f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2) * (k + 3)) / 6;
57515f82726aSMatthew G. Knepley       break;
57525f82726aSMatthew G. Knepley     default:
57535f82726aSMatthew G. Knepley       *dof = 0;
57545f82726aSMatthew G. Knepley     }
57559e8305c2SJed Brown   }
57563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57579e8305c2SJed Brown }
57589e8305c2SJed Brown 
5759a4355906SMatthew Knepley /*@
5760bc1eb3faSJed Brown 
5761bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5762bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
576320f4b53cSBarry Smith   section provided (or the section of the `DM`).
5764a4355906SMatthew Knepley 
5765a4355906SMatthew Knepley   Input Parameters:
576620f4b53cSBarry Smith + dm      - The `DM`
576720f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
576820f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5769a4355906SMatthew Knepley 
5770bc1eb3faSJed Brown   Example:
5771bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5772bc1eb3faSJed Brown .vb
5773bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5774bc1eb3faSJed Brown 
5775bc1eb3faSJed Brown   v4 -- e6 -- v3
5776bc1eb3faSJed Brown   |           |
5777bc1eb3faSJed Brown   e7    c0    e8
5778bc1eb3faSJed Brown   |           |
5779bc1eb3faSJed Brown   v1 -- e5 -- v2
5780bc1eb3faSJed Brown .ve
5781bc1eb3faSJed Brown 
5782bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5783bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5784bc1eb3faSJed Brown .vb
5785bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5786bc1eb3faSJed Brown     v1 -> [4]
5787bc1eb3faSJed Brown     ...
5788bc1eb3faSJed Brown     e5 -> [8, 9]
5789bc1eb3faSJed Brown .ve
5790bc1eb3faSJed Brown 
5791bc1eb3faSJed Brown   which corresponds to the dofs
5792bc1eb3faSJed Brown .vb
5793bc1eb3faSJed Brown     6   10  11  7
5794bc1eb3faSJed Brown     13  2   3   15
5795bc1eb3faSJed Brown     12  0   1   14
5796bc1eb3faSJed Brown     4   8   9   5
5797bc1eb3faSJed Brown .ve
5798bc1eb3faSJed Brown 
5799bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5800bc1eb3faSJed Brown .vb
5801bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5802bc1eb3faSJed Brown .ve
5803bc1eb3faSJed Brown 
5804bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5805bc1eb3faSJed Brown .vb
5806bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5807bc1eb3faSJed Brown .ve
5808bc1eb3faSJed Brown 
5809a4355906SMatthew Knepley   Level: developer
5810a4355906SMatthew Knepley 
5811da9ac489SAlbert Cowie   Notes:
5812a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5813a1cb98faSBarry Smith   degree of the basis.
5814a1cb98faSBarry Smith 
5815da9ac489SAlbert Cowie   This is required to run with libCEED.
5816da9ac489SAlbert Cowie 
58171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5818a4355906SMatthew Knepley @*/
5819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5820d71ae5a4SJacob Faibussowitsch {
58217391a63aSMatthew G. Knepley   DMLabel   label;
5822bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
58235f82726aSMatthew G. Knepley   PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE;
58243194fc30SMatthew G. Knepley 
58253194fc30SMatthew G. Knepley   PetscFunctionBegin;
58269566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
58273ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5828a433471fSStefano Zampini   if (point < 0) {
5829a433471fSStefano Zampini     PetscInt sStart, sEnd;
5830a433471fSStefano Zampini 
58319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5832a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5833a433471fSStefano Zampini   }
58349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
58359566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
58369566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58379371c9d4SSatish Balay   if (depth == 1) {
58389371c9d4SSatish Balay     eStart = point;
58399371c9d4SSatish Balay   } else if (depth == dim) {
58407391a63aSMatthew G. Knepley     const PetscInt *cone;
58417391a63aSMatthew G. Knepley 
58429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5843d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5844d4e6627bSStefano Zampini     else if (dim == 3) {
5845d4e6627bSStefano Zampini       const PetscInt *cone2;
58469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5847d4e6627bSStefano Zampini       eStart = cone2[0];
584863a3b9bcSJacob 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);
584963a3b9bcSJacob 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);
5850e327e467SRezgar Shakeri 
58519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5852bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5853bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5854bb197d40SJed Brown     PetscInt *perm;
5855bb197d40SJed Brown 
58563194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
58575f82726aSMatthew G. Knepley       PetscInt dof;
58585f82726aSMatthew G. Knepley 
58595f82726aSMatthew G. Knepley       PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58605f82726aSMatthew G. Knepley       PetscCheck(dim == 1 || tensor || !continuous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Continuous field %" PetscInt_FMT " must have a tensor product discretization", f);
58615f82726aSMatthew G. Knepley       if (!continuous && d < dim) continue;
58625f82726aSMatthew G. Knepley       PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58635f82726aSMatthew G. Knepley       size += dof * Nc;
58643194fc30SMatthew G. Knepley     }
58659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
58663194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5867bb197d40SJed Brown       switch (d) {
5868babf31e0SJed Brown       case 1:
58695f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58705f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
5871babf31e0SJed Brown         /*
5872babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5873babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5874babf31e0SJed Brown          */
5875e327e467SRezgar Shakeri         if (continuous) {
5876babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
58779371c9d4SSatish Balay           for (i = 0; i < k - 1; i++)
58789371c9d4SSatish Balay             for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5879babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5880babf31e0SJed Brown           foffset = offset;
5881e327e467SRezgar Shakeri         } else {
58825f82726aSMatthew G. Knepley           PetscInt dof;
58835f82726aSMatthew G. Knepley 
58845f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58855f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
58865f82726aSMatthew G. Knepley           foffset = offset;
5887e327e467SRezgar Shakeri         }
5888babf31e0SJed Brown         break;
588989eabcffSMatthew G. Knepley       case 2:
58903194fc30SMatthew 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} */
58915f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58925f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
58933194fc30SMatthew G. Knepley         /* The SEM order is
58943194fc30SMatthew G. Knepley 
58953194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
589689eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
58973194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
58983194fc30SMatthew G. Knepley          */
5899e327e467SRezgar Shakeri         if (continuous) {
59003194fc30SMatthew G. Knepley           const PetscInt of   = 0;
59013194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
59023194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
59033194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
59043194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
59053194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
59063194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
59073194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
59083194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
59093194fc30SMatthew G. Knepley           PetscInt       o;
59103194fc30SMatthew G. Knepley 
59113194fc30SMatthew G. Knepley           /* bottom */
59123194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
59139371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
59149371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59153194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
59163194fc30SMatthew G. Knepley           /* middle */
59173194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
59183194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
59199371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
59209371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59213194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
59223194fc30SMatthew G. Knepley           }
59233194fc30SMatthew G. Knepley           /* top */
59243194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
59259371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
59269371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59273194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
59283194fc30SMatthew G. Knepley           foffset = offset;
5929e327e467SRezgar Shakeri         } else {
59305f82726aSMatthew G. Knepley           PetscInt dof;
59315f82726aSMatthew G. Knepley 
59325f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
59335f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
59345f82726aSMatthew G. Knepley           foffset = offset;
59353194fc30SMatthew G. Knepley         }
593689eabcffSMatthew G. Knepley         break;
593789eabcffSMatthew G. Knepley       case 3:
593889eabcffSMatthew G. Knepley         /* The original hex closure is
593989eabcffSMatthew G. Knepley 
594089eabcffSMatthew G. Knepley          {c,
594189eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
594289eabcffSMatthew 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,
594389eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
594489eabcffSMatthew G. Knepley          */
59455f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
59465f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
594789eabcffSMatthew G. Knepley         /* The SEM order is
594889eabcffSMatthew G. Knepley          Bottom Slice
594989eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
595089eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
595189eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
595289eabcffSMatthew G. Knepley 
595389eabcffSMatthew G. Knepley          Middle Slice (j)
595489eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
595589eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
595689eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
595789eabcffSMatthew G. Knepley 
595889eabcffSMatthew G. Knepley          Top Slice
595989eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
596089eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
596189eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
596289eabcffSMatthew G. Knepley          */
5963e327e467SRezgar Shakeri         if (continuous) {
596489eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
596589eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
596689eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
596789eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
596889eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
596989eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
597089eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
597189eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
597289eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
597389eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
597489eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
597589eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
597689eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
597789eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
597889eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
597989eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
598089eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
598189eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
598289eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
598389eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
598489eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
598589eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
598689eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
598789eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
598889eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
598989eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
599089eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
599189eabcffSMatthew G. Knepley           PetscInt       o, n;
599289eabcffSMatthew G. Knepley 
599389eabcffSMatthew G. Knepley           /* Bottom Slice */
599489eabcffSMatthew G. Knepley           /*   bottom */
599589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
59969371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
59979371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
599889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
599989eabcffSMatthew G. Knepley           /*   middle */
600089eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
600189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
60029371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
60039371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
60049371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
60059371c9d4SSatish Balay             }
600689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
60073194fc30SMatthew G. Knepley           }
600889eabcffSMatthew G. Knepley           /*   top */
600989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
60109371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
60119371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
601289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
601389eabcffSMatthew G. Knepley 
601489eabcffSMatthew G. Knepley           /* Middle Slice */
601589eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
601689eabcffSMatthew G. Knepley             /*   bottom */
601789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
60189371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
60199371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
602089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
602189eabcffSMatthew G. Knepley             /*   middle */
602289eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
602389eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
60249371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
60259371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
602689eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
602789eabcffSMatthew G. Knepley             }
602889eabcffSMatthew G. Knepley             /*   top */
602989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
60309371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
60319371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
603289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
603389eabcffSMatthew G. Knepley           }
603489eabcffSMatthew G. Knepley 
603589eabcffSMatthew G. Knepley           /* Top Slice */
603689eabcffSMatthew G. Knepley           /*   bottom */
603789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
60389371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
60399371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
604089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
604189eabcffSMatthew G. Knepley           /*   middle */
604289eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
604389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
60449371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
60459371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
604689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
604789eabcffSMatthew G. Knepley           }
604889eabcffSMatthew G. Knepley           /*   top */
604989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
60509371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
60519371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
605289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
605389eabcffSMatthew G. Knepley 
605489eabcffSMatthew G. Knepley           foffset = offset;
6055e327e467SRezgar Shakeri         } else {
60565f82726aSMatthew G. Knepley           PetscInt dof;
60575f82726aSMatthew G. Knepley 
60585f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
60595f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
60605f82726aSMatthew G. Knepley           foffset = offset;
606189eabcffSMatthew G. Knepley         }
606289eabcffSMatthew G. Knepley         break;
6063d71ae5a4SJacob Faibussowitsch       default:
6064d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
606589eabcffSMatthew G. Knepley       }
606689eabcffSMatthew G. Knepley     }
606763a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
60683194fc30SMatthew G. Knepley     /* Check permutation */
60693194fc30SMatthew G. Knepley     {
60703194fc30SMatthew G. Knepley       PetscInt *check;
60713194fc30SMatthew G. Knepley 
60729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
60731dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
60741dca8a05SBarry Smith         check[i] = -1;
60751dca8a05SBarry 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]);
60761dca8a05SBarry Smith       }
60773194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
60781dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
60799566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
60803194fc30SMatthew G. Knepley     }
60819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
6082a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
6083a05c9aa3SJed Brown       PetscInt *loc_perm;
60849566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
6085a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
6086a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
6087a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
6088a05c9aa3SJed Brown       }
60899566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
6090a05c9aa3SJed Brown     }
6091bb197d40SJed Brown   }
60923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60933194fc30SMatthew G. Knepley }
60943194fc30SMatthew G. Knepley 
6095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
6096d71ae5a4SJacob Faibussowitsch {
6097e071409bSToby Isaac   PetscDS  prob;
6098e071409bSToby Isaac   PetscInt depth, Nf, h;
6099e071409bSToby Isaac   DMLabel  label;
6100e071409bSToby Isaac 
6101e071409bSToby Isaac   PetscFunctionBeginHot;
61029566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
6103e071409bSToby Isaac   Nf      = prob->Nf;
6104e071409bSToby Isaac   label   = dm->depthLabel;
6105e071409bSToby Isaac   *dspace = NULL;
6106e071409bSToby Isaac   if (field < Nf) {
6107e071409bSToby Isaac     PetscObject disc = prob->disc[field];
6108e071409bSToby Isaac 
6109e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
6110e071409bSToby Isaac       PetscDualSpace dsp;
6111e071409bSToby Isaac 
61129566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
61139566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
61149566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
6115e071409bSToby Isaac       h = depth - 1 - h;
6116e071409bSToby Isaac       if (h) {
61179566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
6118e071409bSToby Isaac       } else {
6119e071409bSToby Isaac         *dspace = dsp;
6120e071409bSToby Isaac       }
6121e071409bSToby Isaac     }
6122e071409bSToby Isaac   }
61233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6124e071409bSToby Isaac }
6125e071409bSToby Isaac 
6126d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6127d71ae5a4SJacob Faibussowitsch {
612828351e22SJed Brown   PetscScalar       *array;
612928351e22SJed Brown   const PetscScalar *vArray;
6130d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
61311a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
6132552f7358SJed Brown 
61331b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
61359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
61369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
61379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
61383f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
61399df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
61409df71ca4SMatthew G. Knepley       PetscInt dof;
6141d9917b9dSMatthew G. Knepley 
61429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
61439df71ca4SMatthew G. Knepley       size += dof;
61449df71ca4SMatthew G. Knepley     }
61459df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
61469df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
61472a3aaacfSMatthew G. Knepley       PetscInt       dof;
61485a1bb5cfSMatthew G. Knepley 
61495a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
61509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
61515a1bb5cfSMatthew G. Knepley       size += dof;
61525a1bb5cfSMatthew G. Knepley     }
61533f7cbbe7SMatthew G. Knepley     if (!values) {
61543f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
61553ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
61563f7cbbe7SMatthew G. Knepley     }
61579566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
6158982e9ed1SMatthew G. Knepley   } else {
6159982e9ed1SMatthew G. Knepley     array = *values;
6160982e9ed1SMatthew G. Knepley   }
61619df71ca4SMatthew G. Knepley   size = 0;
616228351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
61639df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
61649df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
616528351e22SJed Brown     const PetscScalar *varr;
6166d9917b9dSMatthew G. Knepley 
61679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
61689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
61698e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
6170ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61719df71ca4SMatthew G. Knepley     size += dof;
61729df71ca4SMatthew G. Knepley   }
61739df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
61749df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
61759df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
61765a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
617728351e22SJed Brown     const PetscScalar *varr;
61785a1bb5cfSMatthew G. Knepley 
617952ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
61809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
61819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
61828e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
61835a1bb5cfSMatthew G. Knepley     if (o >= 0) {
6184ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61855a1bb5cfSMatthew G. Knepley     } else {
6186ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
61875a1bb5cfSMatthew G. Knepley     }
61889df71ca4SMatthew G. Knepley     size += dof;
61895a1bb5cfSMatthew G. Knepley   }
619028351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
61919df71ca4SMatthew G. Knepley   if (!*values) {
61925a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
61935a1bb5cfSMatthew G. Knepley     *values = array;
61949df71ca4SMatthew G. Knepley   } else {
619563a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
61968c312ff3SMatthew G. Knepley     *csize = size;
61979df71ca4SMatthew G. Knepley   }
61983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61995a1bb5cfSMatthew G. Knepley }
6200d9917b9dSMatthew G. Knepley 
620127f02ce8SMatthew G. Knepley /* Compress out points not in the section */
6202d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
6203d71ae5a4SJacob Faibussowitsch {
620427f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
620527f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
620627f02ce8SMatthew G. Knepley 
62079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
620827f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
620927f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
621027f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
621127f02ce8SMatthew G. Knepley       points[q * 2]     = r;
621227f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
621327f02ce8SMatthew G. Knepley       ++q;
621427f02ce8SMatthew G. Knepley     }
621527f02ce8SMatthew G. Knepley   }
621627f02ce8SMatthew G. Knepley   *numPoints = q;
62173ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
621827f02ce8SMatthew G. Knepley }
621927f02ce8SMatthew G. Knepley 
622097529cf3SJed Brown /* Compressed closure does not apply closure permutation */
622107218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6222d71ae5a4SJacob Faibussowitsch {
622327f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
6224923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
6225923c78e0SToby Isaac 
6226923c78e0SToby Isaac   PetscFunctionBeginHot;
62279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
622807218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
6229923c78e0SToby Isaac     PetscInt dof, off;
6230923c78e0SToby Isaac 
62319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
62329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
62339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
6234923c78e0SToby Isaac     np  = dof / 2;
62358e3a54c0SPierre Jolivet     pts = PetscSafePointerPlusOffset((PetscInt *)cla, off);
623627f02ce8SMatthew G. Knepley   } else {
623707218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
62389566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
6239923c78e0SToby Isaac   }
6240923c78e0SToby Isaac   *numPoints = np;
6241923c78e0SToby Isaac   *points    = pts;
6242923c78e0SToby Isaac   *clp       = cla;
62433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6244923c78e0SToby Isaac }
6245923c78e0SToby Isaac 
6246d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6247d71ae5a4SJacob Faibussowitsch {
6248923c78e0SToby Isaac   PetscFunctionBeginHot;
6249923c78e0SToby Isaac   if (!*clPoints) {
62509566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
6251923c78e0SToby Isaac   } else {
62529566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
6253923c78e0SToby Isaac   }
6254923c78e0SToby Isaac   *numPoints = 0;
6255923c78e0SToby Isaac   *points    = NULL;
6256923c78e0SToby Isaac   *clSec     = NULL;
6257923c78e0SToby Isaac   *clPoints  = NULL;
6258923c78e0SToby Isaac   *clp       = NULL;
62593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6260923c78e0SToby Isaac }
6261923c78e0SToby Isaac 
6262d71ae5a4SJacob 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[])
6263d71ae5a4SJacob Faibussowitsch {
62641a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
626597e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
626697e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
62671a271a75SMatthew G. Knepley 
62681a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6269fe02ba77SJed Brown   *size = 0;
62709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
627197e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
627297e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
627397e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
627497e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
62751a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
62761a271a75SMatthew G. Knepley     const PetscScalar *varr;
62771a271a75SMatthew G. Knepley 
62789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
62799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
62808e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
628197e99dd9SToby Isaac     if (clperm) {
628297e99dd9SToby Isaac       if (perm) {
628397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
62841a271a75SMatthew G. Knepley       } else {
628597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
628697e99dd9SToby Isaac       }
628797e99dd9SToby Isaac       if (flip) {
628897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
628997e99dd9SToby Isaac       }
629097e99dd9SToby Isaac     } else {
629197e99dd9SToby Isaac       if (perm) {
629297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
629397e99dd9SToby Isaac       } else {
629497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
629597e99dd9SToby Isaac       }
629697e99dd9SToby Isaac       if (flip) {
629797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
62981a271a75SMatthew G. Knepley       }
62991a271a75SMatthew G. Knepley     }
630097e99dd9SToby Isaac     offset += dof;
630197e99dd9SToby Isaac   }
63029566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
63031a271a75SMatthew G. Knepley   *size = offset;
63043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63051a271a75SMatthew G. Knepley }
63061a271a75SMatthew G. Knepley 
6307d71ae5a4SJacob 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[])
6308d71ae5a4SJacob Faibussowitsch {
63091a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
63101a271a75SMatthew G. Knepley 
63111a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6312fe02ba77SJed Brown   *size = 0;
63131a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
631497e99dd9SToby Isaac     PetscInt            p;
631597e99dd9SToby Isaac     const PetscInt    **perms = NULL;
631697e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63171a271a75SMatthew G. Knepley 
63189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
631997e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
632097e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
632197e99dd9SToby Isaac       PetscInt           fdof, foff, b;
63221a271a75SMatthew G. Knepley       const PetscScalar *varr;
632397e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
632497e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
63251a271a75SMatthew G. Knepley 
63269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63281a271a75SMatthew G. Knepley       varr = &vArray[foff];
632997e99dd9SToby Isaac       if (clperm) {
63309371c9d4SSatish Balay         if (perm) {
6331ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
63321a271a75SMatthew G. Knepley         } else {
6333ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
63349371c9d4SSatish Balay         }
63359371c9d4SSatish Balay         if (flip) {
6336ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
63379371c9d4SSatish Balay         }
63389371c9d4SSatish Balay       } else {
63399371c9d4SSatish Balay         if (perm) {
6340ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
63419371c9d4SSatish Balay         } else {
6342ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
63439371c9d4SSatish Balay         }
63449371c9d4SSatish Balay         if (flip) {
6345ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
63469371c9d4SSatish Balay         }
63471a271a75SMatthew G. Knepley       }
634897e99dd9SToby Isaac       offset += fdof;
63491a271a75SMatthew G. Knepley     }
63509566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
63511a271a75SMatthew G. Knepley   }
63521a271a75SMatthew G. Knepley   *size = offset;
63533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63541a271a75SMatthew G. Knepley }
63551a271a75SMatthew G. Knepley 
6356e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
635707218a29SMatthew G. Knepley {
635807218a29SMatthew G. Knepley   PetscSection    clSection;
635907218a29SMatthew G. Knepley   IS              clPoints;
636007218a29SMatthew G. Knepley   PetscInt       *points = NULL;
6361e8e188d2SZach Atkins   const PetscInt *clp, *perm = NULL;
636207218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
636307218a29SMatthew G. Knepley 
636407218a29SMatthew G. Knepley   PetscFunctionBeginHot;
636507218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
636607218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
636707218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6368e8e188d2SZach Atkins   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
636907218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
637007218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
637107218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
637207218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
637307218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
637407218a29SMatthew G. Knepley   }
637507218a29SMatthew G. Knepley   /* Get points */
637607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
637707218a29SMatthew G. Knepley   /* Get sizes */
637807218a29SMatthew G. Knepley   asize = 0;
637907218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
638007218a29SMatthew G. Knepley     PetscInt dof;
638107218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
638207218a29SMatthew G. Knepley     asize += dof;
638307218a29SMatthew G. Knepley   }
638407218a29SMatthew G. Knepley   if (values) {
638507218a29SMatthew G. Knepley     const PetscScalar *vArray;
638607218a29SMatthew G. Knepley     PetscInt           size;
638707218a29SMatthew G. Knepley 
638807218a29SMatthew G. Knepley     if (*values) {
638907218a29SMatthew 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);
639007218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
6391e8e188d2SZach Atkins     if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
639207218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
639307218a29SMatthew G. Knepley     /* Get values */
639407218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
639507218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
639607218a29SMatthew 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);
639707218a29SMatthew G. Knepley     /* Cleanup array */
639807218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
639907218a29SMatthew G. Knepley   }
640007218a29SMatthew G. Knepley   if (csize) *csize = asize;
640107218a29SMatthew G. Knepley   /* Cleanup points */
640207218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
640307218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
640407218a29SMatthew G. Knepley }
640507218a29SMatthew G. Knepley 
6406552f7358SJed Brown /*@C
6407552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6408552f7358SJed Brown 
6409552f7358SJed Brown   Not collective
6410552f7358SJed Brown 
6411552f7358SJed Brown   Input Parameters:
6412a1cb98faSBarry Smith + dm      - The `DM`
641320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6414552f7358SJed Brown . v       - The local vector
6415a1cb98faSBarry Smith - point   - The point in the `DM`
6416552f7358SJed Brown 
64176b867d5aSJose E. Roman   Input/Output Parameters:
641820f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
641920f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
642020f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
642122c1ee49SMatthew G. Knepley 
6422552f7358SJed Brown   Level: intermediate
6423552f7358SJed Brown 
6424a1cb98faSBarry Smith   Notes:
642520f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6426a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6427a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6428a1cb98faSBarry Smith 
6429a1cb98faSBarry Smith   A typical use could be
6430a1cb98faSBarry Smith .vb
6431a1cb98faSBarry Smith    values = NULL;
6432a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6433a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6434a1cb98faSBarry Smith      <Compute on closure>
6435a1cb98faSBarry Smith    }
6436a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6437a1cb98faSBarry Smith .ve
6438a1cb98faSBarry Smith   or
6439a1cb98faSBarry Smith .vb
6440a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6441a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6442a1cb98faSBarry Smith      clSize = clMaxSize;
6443a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6444a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6445a1cb98faSBarry Smith        <Compute on closure>
6446a1cb98faSBarry Smith      }
6447a1cb98faSBarry Smith    }
6448a1cb98faSBarry Smith    PetscFree(values);
6449a1cb98faSBarry Smith .ve
6450a1cb98faSBarry Smith 
645160225df5SJacob Faibussowitsch   Fortran Notes:
645220f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6453a1cb98faSBarry Smith 
64541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6455552f7358SJed Brown @*/
6456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6457d71ae5a4SJacob Faibussowitsch {
6458d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
6459e8e188d2SZach Atkins   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values));
64603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6461552f7358SJed Brown }
6462552f7358SJed Brown 
6463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6464d71ae5a4SJacob Faibussowitsch {
6465e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6466e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6467e5c487bfSMatthew G. Knepley   IS                 clPoints;
6468e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6469e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6470e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6471c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6472c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6473e5c487bfSMatthew G. Knepley 
6474e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6475e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64769566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6477e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6478e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
64809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
64819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6482e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
64839566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
64843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6485e5c487bfSMatthew G. Knepley   }
6486e5c487bfSMatthew G. Knepley   /* Get points */
648707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6488c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6489c459fbc1SJed Brown     PetscInt dof;
64909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6491c459fbc1SJed Brown     clsize += dof;
6492c459fbc1SJed Brown   }
64939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6494e5c487bfSMatthew G. Knepley   /* Filter points */
6495e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6496e5c487bfSMatthew G. Knepley     PetscInt dep;
6497e5c487bfSMatthew G. Knepley 
64989566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6499e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6500e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6501e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6502e5c487bfSMatthew G. Knepley     ++Np;
6503e5c487bfSMatthew G. Knepley   }
6504e5c487bfSMatthew G. Knepley   /* Get array */
6505e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6506e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6507e5c487bfSMatthew G. Knepley 
6508e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
65099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6510e5c487bfSMatthew G. Knepley       asize += dof;
6511e5c487bfSMatthew G. Knepley     }
6512e5c487bfSMatthew G. Knepley     if (!values) {
65139566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6514e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
65153ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6516e5c487bfSMatthew G. Knepley     }
65179566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6518e5c487bfSMatthew G. Knepley   } else {
6519e5c487bfSMatthew G. Knepley     array = *values;
6520e5c487bfSMatthew G. Knepley   }
65219566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6522e5c487bfSMatthew G. Knepley   /* Get values */
65239566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
65249566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6525e5c487bfSMatthew G. Knepley   /* Cleanup points */
65269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6527e5c487bfSMatthew G. Knepley   /* Cleanup array */
65289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6529e5c487bfSMatthew G. Knepley   if (!*values) {
6530e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6531e5c487bfSMatthew G. Knepley     *values = array;
6532e5c487bfSMatthew G. Knepley   } else {
653363a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6534e5c487bfSMatthew G. Knepley     *csize = size;
6535e5c487bfSMatthew G. Knepley   }
65363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6537e5c487bfSMatthew G. Knepley }
6538e5c487bfSMatthew G. Knepley 
6539552f7358SJed Brown /*@C
6540552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6541552f7358SJed Brown 
6542552f7358SJed Brown   Not collective
6543552f7358SJed Brown 
6544552f7358SJed Brown   Input Parameters:
6545a1cb98faSBarry Smith + dm      - The `DM`
654620f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6547552f7358SJed Brown . v       - The local vector
6548a1cb98faSBarry Smith . point   - The point in the `DM`
654920f4b53cSBarry Smith . csize   - The number of values in the closure, or `NULL`
6550552f7358SJed Brown - values  - The array of values, which is a borrowed array and should not be freed
6551552f7358SJed Brown 
6552552f7358SJed Brown   Level: intermediate
6553552f7358SJed Brown 
6554a1cb98faSBarry Smith   Note:
655520f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6556a1cb98faSBarry Smith 
655760225df5SJacob Faibussowitsch   Fortran Notes:
655820f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6559a1cb98faSBarry Smith 
65601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6561552f7358SJed Brown @*/
6562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6563d71ae5a4SJacob Faibussowitsch {
6564552f7358SJed Brown   PetscInt size = 0;
6565552f7358SJed Brown 
6566552f7358SJed Brown   PetscFunctionBegin;
6567552f7358SJed Brown   /* Should work without recalculating size */
65689566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6569c9fdaa05SMatthew G. Knepley   *values = NULL;
65703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6571552f7358SJed Brown }
6572552f7358SJed Brown 
6573d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6574d71ae5a4SJacob Faibussowitsch {
65759371c9d4SSatish Balay   *x += y;
65769371c9d4SSatish Balay }
6577d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6578d71ae5a4SJacob Faibussowitsch {
65799371c9d4SSatish Balay   *x = y;
65809371c9d4SSatish Balay }
6581552f7358SJed Brown 
6582d71ae5a4SJacob 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[])
6583d71ae5a4SJacob Faibussowitsch {
6584552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6585552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6586552f7358SJed Brown   PetscScalar    *a;
6587552f7358SJed Brown   PetscInt        off, cind = 0, k;
6588552f7358SJed Brown 
6589552f7358SJed Brown   PetscFunctionBegin;
65909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
65919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6592552f7358SJed Brown   a = &array[off];
6593552f7358SJed Brown   if (!cdof || setBC) {
659497e99dd9SToby Isaac     if (clperm) {
65959371c9d4SSatish Balay       if (perm) {
6596ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6597552f7358SJed Brown       } else {
6598ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
65999371c9d4SSatish Balay       }
66009371c9d4SSatish Balay     } else {
66019371c9d4SSatish Balay       if (perm) {
6602ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
66039371c9d4SSatish Balay       } else {
6604ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
66059371c9d4SSatish Balay       }
6606552f7358SJed Brown     }
6607552f7358SJed Brown   } else {
66089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
660997e99dd9SToby Isaac     if (clperm) {
66109371c9d4SSatish Balay       if (perm) {
66119371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
66129371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66139371c9d4SSatish Balay             ++cind;
66149371c9d4SSatish Balay             continue;
66159371c9d4SSatish Balay           }
661697e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6617552f7358SJed Brown         }
6618552f7358SJed Brown       } else {
6619552f7358SJed Brown         for (k = 0; k < dof; ++k) {
66209371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66219371c9d4SSatish Balay             ++cind;
66229371c9d4SSatish Balay             continue;
66239371c9d4SSatish Balay           }
662497e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
662597e99dd9SToby Isaac         }
662697e99dd9SToby Isaac       }
662797e99dd9SToby Isaac     } else {
662897e99dd9SToby Isaac       if (perm) {
662997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66309371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66319371c9d4SSatish Balay             ++cind;
66329371c9d4SSatish Balay             continue;
66339371c9d4SSatish Balay           }
663497e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
663597e99dd9SToby Isaac         }
663697e99dd9SToby Isaac       } else {
663797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66389371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66399371c9d4SSatish Balay             ++cind;
66409371c9d4SSatish Balay             continue;
66419371c9d4SSatish Balay           }
664297e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
664397e99dd9SToby Isaac         }
6644552f7358SJed Brown       }
6645552f7358SJed Brown     }
6646552f7358SJed Brown   }
66473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6648552f7358SJed Brown }
6649552f7358SJed Brown 
6650d71ae5a4SJacob 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[])
6651d71ae5a4SJacob Faibussowitsch {
6652a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6653a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6654a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6655a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6656a5e93ea8SMatthew G. Knepley 
6657a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
66589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
66599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6660a5e93ea8SMatthew G. Knepley   a = &array[off];
6661a5e93ea8SMatthew G. Knepley   if (cdof) {
66629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
666397e99dd9SToby Isaac     if (clperm) {
666497e99dd9SToby Isaac       if (perm) {
6665a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6666a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
666797e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
666897e99dd9SToby Isaac             cind++;
6669a5e93ea8SMatthew G. Knepley           }
6670a5e93ea8SMatthew G. Knepley         }
6671a5e93ea8SMatthew G. Knepley       } else {
6672a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6673a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
667497e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
667597e99dd9SToby Isaac             cind++;
667697e99dd9SToby Isaac           }
667797e99dd9SToby Isaac         }
667897e99dd9SToby Isaac       }
667997e99dd9SToby Isaac     } else {
668097e99dd9SToby Isaac       if (perm) {
668197e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
668297e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
668397e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
668497e99dd9SToby Isaac             cind++;
668597e99dd9SToby Isaac           }
668697e99dd9SToby Isaac         }
668797e99dd9SToby Isaac       } else {
668897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
668997e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
669097e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
669197e99dd9SToby Isaac             cind++;
669297e99dd9SToby Isaac           }
6693a5e93ea8SMatthew G. Knepley         }
6694a5e93ea8SMatthew G. Knepley       }
6695a5e93ea8SMatthew G. Knepley     }
6696a5e93ea8SMatthew G. Knepley   }
66973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6698a5e93ea8SMatthew G. Knepley }
6699a5e93ea8SMatthew G. Knepley 
6700d71ae5a4SJacob 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[])
6701d71ae5a4SJacob Faibussowitsch {
6702552f7358SJed Brown   PetscScalar    *a;
67031a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67041a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
670597e99dd9SToby Isaac   PetscInt        cind = 0, b;
6706552f7358SJed Brown 
6707552f7358SJed Brown   PetscFunctionBegin;
67089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67111a271a75SMatthew G. Knepley   a = &array[foff];
6712552f7358SJed Brown   if (!fcdof || setBC) {
671397e99dd9SToby Isaac     if (clperm) {
67149371c9d4SSatish Balay       if (perm) {
6715ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6716552f7358SJed Brown       } else {
6717ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
67189371c9d4SSatish Balay       }
67199371c9d4SSatish Balay     } else {
67209371c9d4SSatish Balay       if (perm) {
6721ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
67229371c9d4SSatish Balay       } else {
6723ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
67249371c9d4SSatish Balay       }
6725552f7358SJed Brown     }
6726552f7358SJed Brown   } else {
67279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
672897e99dd9SToby Isaac     if (clperm) {
672997e99dd9SToby Isaac       if (perm) {
673097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67319371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67329371c9d4SSatish Balay             ++cind;
67339371c9d4SSatish Balay             continue;
67349371c9d4SSatish Balay           }
673597e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6736552f7358SJed Brown         }
6737552f7358SJed Brown       } else {
673897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67399371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67409371c9d4SSatish Balay             ++cind;
67419371c9d4SSatish Balay             continue;
67429371c9d4SSatish Balay           }
674397e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
674497e99dd9SToby Isaac         }
674597e99dd9SToby Isaac       }
674697e99dd9SToby Isaac     } else {
674797e99dd9SToby Isaac       if (perm) {
674897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67499371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67509371c9d4SSatish Balay             ++cind;
67519371c9d4SSatish Balay             continue;
67529371c9d4SSatish Balay           }
675397e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
675497e99dd9SToby Isaac         }
675597e99dd9SToby Isaac       } else {
675697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67579371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67589371c9d4SSatish Balay             ++cind;
67599371c9d4SSatish Balay             continue;
67609371c9d4SSatish Balay           }
676197e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6762552f7358SJed Brown         }
6763552f7358SJed Brown       }
6764552f7358SJed Brown     }
6765552f7358SJed Brown   }
67661a271a75SMatthew G. Knepley   *offset += fdof;
67673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6768552f7358SJed Brown }
6769552f7358SJed Brown 
6770d71ae5a4SJacob 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[])
6771d71ae5a4SJacob Faibussowitsch {
6772a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
67731a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67741a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67755da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6776ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6777a5e93ea8SMatthew G. Knepley 
6778a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
67799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
67809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67831a271a75SMatthew G. Knepley   a = &array[foff];
6784a5e93ea8SMatthew G. Knepley   if (fcdof) {
6785ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
67869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
678797e99dd9SToby Isaac     if (clperm) {
678897e99dd9SToby Isaac       if (perm) {
6789ba322698SMatthew G. Knepley         if (comps) {
6790ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6791ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
67929371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
67939371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
67949371c9d4SSatish Balay               ncSet = PETSC_TRUE;
67959371c9d4SSatish Balay             }
67969371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
67979371c9d4SSatish Balay               ++cind;
67989371c9d4SSatish Balay               fcSet = PETSC_TRUE;
67999371c9d4SSatish Balay             }
6800ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6801ba322698SMatthew G. Knepley           }
6802ba322698SMatthew G. Knepley         } else {
680397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
680497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
680597e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6806a5e93ea8SMatthew G. Knepley               ++cind;
6807a5e93ea8SMatthew G. Knepley             }
6808a5e93ea8SMatthew G. Knepley           }
6809ba322698SMatthew G. Knepley         }
6810ba322698SMatthew G. Knepley       } else {
6811ba322698SMatthew G. Knepley         if (comps) {
6812ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6813ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68149371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68159371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68169371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68179371c9d4SSatish Balay             }
68189371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68199371c9d4SSatish Balay               ++cind;
68209371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68219371c9d4SSatish Balay             }
6822ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6823ba322698SMatthew G. Knepley           }
6824a5e93ea8SMatthew G. Knepley         } else {
682597e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
682697e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
682797e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
682897e99dd9SToby Isaac               ++cind;
682997e99dd9SToby Isaac             }
683097e99dd9SToby Isaac           }
683197e99dd9SToby Isaac         }
6832ba322698SMatthew G. Knepley       }
683397e99dd9SToby Isaac     } else {
683497e99dd9SToby Isaac       if (perm) {
6835ba322698SMatthew G. Knepley         if (comps) {
6836ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6837ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68389371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68399371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68409371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68419371c9d4SSatish Balay             }
68429371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68439371c9d4SSatish Balay               ++cind;
68449371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68459371c9d4SSatish Balay             }
6846ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6847ba322698SMatthew G. Knepley           }
6848ba322698SMatthew G. Knepley         } else {
684997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
685097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
685197e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
685297e99dd9SToby Isaac               ++cind;
685397e99dd9SToby Isaac             }
685497e99dd9SToby Isaac           }
6855ba322698SMatthew G. Knepley         }
6856ba322698SMatthew G. Knepley       } else {
6857ba322698SMatthew G. Knepley         if (comps) {
6858ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6859ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68609371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68619371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68629371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68639371c9d4SSatish Balay             }
68649371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68659371c9d4SSatish Balay               ++cind;
68669371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68679371c9d4SSatish Balay             }
6868ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6869ba322698SMatthew G. Knepley           }
687097e99dd9SToby Isaac         } else {
687197e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
687297e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
687397e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6874a5e93ea8SMatthew G. Knepley               ++cind;
6875a5e93ea8SMatthew G. Knepley             }
6876a5e93ea8SMatthew G. Knepley           }
6877a5e93ea8SMatthew G. Knepley         }
6878a5e93ea8SMatthew G. Knepley       }
6879a5e93ea8SMatthew G. Knepley     }
6880ba322698SMatthew G. Knepley   }
68811a271a75SMatthew G. Knepley   *offset += fdof;
68823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6883a5e93ea8SMatthew G. Knepley }
6884a5e93ea8SMatthew G. Knepley 
6885d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6886d71ae5a4SJacob Faibussowitsch {
6887552f7358SJed Brown   PetscScalar    *array;
68881b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
68891b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6890552f7358SJed Brown 
68911b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
68929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
68939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
68949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
68959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
68969566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6897b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6898b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6899b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6900b6ebb6e6SMatthew G. Knepley 
69019371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
69029371c9d4SSatish Balay       dof = 0;
69039371c9d4SSatish Balay       continue;
69049371c9d4SSatish Balay     }
69059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6906b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6907b6ebb6e6SMatthew G. Knepley     {
6908b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6909b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6910b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6911b6ebb6e6SMatthew G. Knepley 
69129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
69139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6914b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6915b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6916b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6917ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6918b6ebb6e6SMatthew G. Knepley         } else {
6919ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6920b6ebb6e6SMatthew G. Knepley         }
6921b6ebb6e6SMatthew G. Knepley       } else {
69229566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6923b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6924b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69259371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69269371c9d4SSatish Balay               ++cind;
69279371c9d4SSatish Balay               continue;
69289371c9d4SSatish Balay             }
6929b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6930b6ebb6e6SMatthew G. Knepley           }
6931b6ebb6e6SMatthew G. Knepley         } else {
6932b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69339371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69349371c9d4SSatish Balay               ++cind;
69359371c9d4SSatish Balay               continue;
69369371c9d4SSatish Balay             }
6937b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6938b6ebb6e6SMatthew G. Knepley           }
6939b6ebb6e6SMatthew G. Knepley         }
6940b6ebb6e6SMatthew G. Knepley       }
6941b6ebb6e6SMatthew G. Knepley     }
6942b6ebb6e6SMatthew G. Knepley   }
69439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6945b6ebb6e6SMatthew G. Knepley }
69461b406b76SMatthew G. Knepley 
69471b406b76SMatthew G. Knepley /*@C
694820f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
69491b406b76SMatthew G. Knepley 
69501b406b76SMatthew G. Knepley   Not collective
69511b406b76SMatthew G. Knepley 
69521b406b76SMatthew G. Knepley   Input Parameters:
6953a1cb98faSBarry Smith + dm      - The `DM`
695420f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
69551b406b76SMatthew G. Knepley . v       - The local vector
695620f4b53cSBarry Smith . point   - The point in the `DM`
69571b406b76SMatthew G. Knepley . values  - The array of values
6958a1cb98faSBarry Smith - mode    - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6959a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
69601b406b76SMatthew G. Knepley 
69611b406b76SMatthew G. Knepley   Level: intermediate
69621b406b76SMatthew G. Knepley 
69631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
69641b406b76SMatthew G. Knepley @*/
6965d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6966d71ae5a4SJacob Faibussowitsch {
69671b406b76SMatthew G. Knepley   PetscSection    clSection;
69681b406b76SMatthew G. Knepley   IS              clPoints;
69691b406b76SMatthew G. Knepley   PetscScalar    *array;
69701b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
697127f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6972c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
69731b406b76SMatthew G. Knepley 
69741a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
69751b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69769566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
69771a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
69781a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
69799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
69809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
69811b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
69829566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
69833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
69841b406b76SMatthew G. Knepley   }
69851a271a75SMatthew G. Knepley   /* Get points */
698607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6987c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6988c459fbc1SJed Brown     PetscInt dof;
69899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6990c459fbc1SJed Brown     clsize += dof;
6991c459fbc1SJed Brown   }
69929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
69931a271a75SMatthew G. Knepley   /* Get array */
69949566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
69951a271a75SMatthew G. Knepley   /* Get values */
6996ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
699797e99dd9SToby Isaac     PetscInt offset = 0, f;
6998552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
699997e99dd9SToby Isaac       const PetscInt    **perms = NULL;
700097e99dd9SToby Isaac       const PetscScalar **flips = NULL;
700197e99dd9SToby Isaac 
70029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7003552f7358SJed Brown       switch (mode) {
7004552f7358SJed Brown       case INSERT_VALUES:
700597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
700697e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
700797e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
700897e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70093ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
70109371c9d4SSatish Balay         }
70119371c9d4SSatish Balay         break;
7012552f7358SJed Brown       case INSERT_ALL_VALUES:
701397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
701497e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
701597e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
701697e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70173ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
70189371c9d4SSatish Balay         }
70199371c9d4SSatish Balay         break;
7020a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
702197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
702297e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
702397e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
702497e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70253ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
70269371c9d4SSatish Balay         }
70279371c9d4SSatish Balay         break;
7028552f7358SJed Brown       case ADD_VALUES:
702997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
703097e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
703197e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
703297e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70333ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
70349371c9d4SSatish Balay         }
70359371c9d4SSatish Balay         break;
7036552f7358SJed Brown       case ADD_ALL_VALUES:
703797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
703897e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
703997e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
704097e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70413ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
70429371c9d4SSatish Balay         }
70439371c9d4SSatish Balay         break;
7044304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
704597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
704697e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
704797e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
704897e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70493ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
70509371c9d4SSatish Balay         }
70519371c9d4SSatish Balay         break;
7052d71ae5a4SJacob Faibussowitsch       default:
7053d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7054552f7358SJed Brown       }
70559566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
70561a271a75SMatthew G. Knepley     }
7057552f7358SJed Brown   } else {
70581a271a75SMatthew G. Knepley     PetscInt            dof, off;
705997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
706097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
70611a271a75SMatthew G. Knepley 
70629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
7063552f7358SJed Brown     switch (mode) {
7064552f7358SJed Brown     case INSERT_VALUES:
706597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
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;
70699566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70703ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
70719371c9d4SSatish Balay       }
70729371c9d4SSatish Balay       break;
7073552f7358SJed Brown     case INSERT_ALL_VALUES:
707497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
707597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
707697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
707797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70793ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
70809371c9d4SSatish Balay       }
70819371c9d4SSatish Balay       break;
7082a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
708397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
708497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
708597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
708697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70879566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70883ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
70899371c9d4SSatish Balay       }
70909371c9d4SSatish Balay       break;
7091552f7358SJed Brown     case ADD_VALUES:
709297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
709397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
709497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
709597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70973ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
70989371c9d4SSatish Balay       }
70999371c9d4SSatish Balay       break;
7100552f7358SJed Brown     case ADD_ALL_VALUES:
710197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
710297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
710397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
710497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71063ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
71079371c9d4SSatish Balay       }
71089371c9d4SSatish Balay       break;
7109304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
711097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
711197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
711297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
711397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71149566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71153ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
71169371c9d4SSatish Balay       }
71179371c9d4SSatish Balay       break;
7118d71ae5a4SJacob Faibussowitsch     default:
7119d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7120552f7358SJed Brown     }
71219566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
7122552f7358SJed Brown   }
71231a271a75SMatthew G. Knepley   /* Cleanup points */
71249566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
71251a271a75SMatthew G. Knepley   /* Cleanup array */
71269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
71273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7128552f7358SJed Brown }
7129552f7358SJed Brown 
71305f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
7131d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
7132d71ae5a4SJacob Faibussowitsch {
71335f790a90SMatthew G. Knepley   PetscFunctionBegin;
713411cc89d2SBarry Smith   *contains = PETSC_TRUE;
71355f790a90SMatthew G. Knepley   if (label) {
7136d6177c40SToby Isaac     PetscInt fdof;
71375f790a90SMatthew G. Knepley 
713811cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
713911cc89d2SBarry Smith     if (!*contains) {
71409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
71415f790a90SMatthew G. Knepley       *offset += fdof;
71423ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
71435f790a90SMatthew G. Knepley     }
71445f790a90SMatthew G. Knepley   }
71453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71465f790a90SMatthew G. Knepley }
71475f790a90SMatthew G. Knepley 
714897529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
7149d71ae5a4SJacob 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)
7150d71ae5a4SJacob Faibussowitsch {
7151e07394fbSMatthew G. Knepley   PetscSection    clSection;
7152e07394fbSMatthew G. Knepley   IS              clPoints;
7153e07394fbSMatthew G. Knepley   PetscScalar    *array;
7154e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
715597529cf3SJed Brown   const PetscInt *clp;
7156e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
715797e99dd9SToby Isaac   PetscInt        offset = 0, f;
7158e07394fbSMatthew G. Knepley 
7159e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
7160e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71619566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
7162e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7163e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
71649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7165e07394fbSMatthew G. Knepley   /* Get points */
716607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
7167e07394fbSMatthew G. Knepley   /* Get array */
71689566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
7169e07394fbSMatthew G. Knepley   /* Get values */
7170e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
717197e99dd9SToby Isaac     const PetscInt    **perms = NULL;
717297e99dd9SToby Isaac     const PetscScalar **flips = NULL;
717311cc89d2SBarry Smith     PetscBool           contains;
717497e99dd9SToby Isaac 
7175e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
7176e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
7177e07394fbSMatthew G. Knepley         PetscInt fdof;
71789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
7179e07394fbSMatthew G. Knepley         offset += fdof;
7180e07394fbSMatthew G. Knepley       }
7181e07394fbSMatthew G. Knepley       continue;
7182e07394fbSMatthew G. Knepley     }
71839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7184e07394fbSMatthew G. Knepley     switch (mode) {
7185e07394fbSMatthew G. Knepley     case INSERT_VALUES:
718697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
718797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
718897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
718997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
719011cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
719111cc89d2SBarry Smith         if (!contains) continue;
71929566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
71939371c9d4SSatish Balay       }
71949371c9d4SSatish Balay       break;
7195e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
719697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
719797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
719897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
719997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
720011cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
720111cc89d2SBarry Smith         if (!contains) continue;
72029566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
72039371c9d4SSatish Balay       }
72049371c9d4SSatish Balay       break;
7205e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
720697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
720797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
720897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
720997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
721011cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
721111cc89d2SBarry Smith         if (!contains) continue;
72129566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
72139371c9d4SSatish Balay       }
72149371c9d4SSatish Balay       break;
7215e07394fbSMatthew G. Knepley     case ADD_VALUES:
721697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
721797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
721897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
721997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
722011cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
722111cc89d2SBarry Smith         if (!contains) continue;
72229566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
72239371c9d4SSatish Balay       }
72249371c9d4SSatish Balay       break;
7225e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
722697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
722797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
722897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
722997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
723011cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
723111cc89d2SBarry Smith         if (!contains) continue;
72329566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
72339371c9d4SSatish Balay       }
72349371c9d4SSatish Balay       break;
7235d71ae5a4SJacob Faibussowitsch     default:
7236d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7237e07394fbSMatthew G. Knepley     }
72389566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7239e07394fbSMatthew G. Knepley   }
7240e07394fbSMatthew G. Knepley   /* Cleanup points */
72419566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
7242e07394fbSMatthew G. Knepley   /* Cleanup array */
72439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
72443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7245e07394fbSMatthew G. Knepley }
7246e07394fbSMatthew G. Knepley 
7247d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
7248d71ae5a4SJacob Faibussowitsch {
7249552f7358SJed Brown   PetscMPIInt rank;
7250552f7358SJed Brown   PetscInt    i, j;
7251552f7358SJed Brown 
7252552f7358SJed Brown   PetscFunctionBegin;
72539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
725463a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
725563a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
725663a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
7257b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
72583ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
7259b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
72609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
7261b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
7262519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
72639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
7264552f7358SJed Brown #else
72659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
7266552f7358SJed Brown #endif
7267552f7358SJed Brown     }
72689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
7269552f7358SJed Brown   }
72703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7271552f7358SJed Brown }
7272552f7358SJed Brown 
727305586334SMatthew G. Knepley /*
727405586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
727505586334SMatthew G. Knepley 
727605586334SMatthew G. Knepley   Input Parameters:
727705586334SMatthew G. Knepley + section - The section for this data layout
727836fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
727905586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
728005586334SMatthew G. Knepley . off     - The global offset of this point
728105586334SMatthew G. Knepley . loff    - The local offset of each field
7282a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
728305586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
728405586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
728505586334SMatthew G. Knepley 
728605586334SMatthew G. Knepley   Output Parameter:
728705586334SMatthew G. Knepley . indices - Indices for dofs on this point
728805586334SMatthew G. Knepley 
728905586334SMatthew G. Knepley   Level: developer
729005586334SMatthew G. Knepley 
729105586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
729205586334SMatthew G. Knepley */
7293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
7294d71ae5a4SJacob Faibussowitsch {
7295e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
7296552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7297552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7298552f7358SJed Brown   PetscInt        cind = 0, k;
7299552f7358SJed Brown 
7300552f7358SJed Brown   PetscFunctionBegin;
730108401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
73039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
7304552f7358SJed Brown   if (!cdof || setBC) {
730505586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
730605586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
730705586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
730805586334SMatthew G. Knepley 
730905586334SMatthew G. Knepley       indices[ind] = off + k;
7310552f7358SJed Brown     }
7311552f7358SJed Brown   } else {
73129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
73134acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
731405586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
731505586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
731605586334SMatthew G. Knepley 
73174acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
73184acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
731905586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
73204acb8e1eSToby Isaac         ++cind;
73214acb8e1eSToby Isaac       } else {
732236fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7323552f7358SJed Brown       }
7324552f7358SJed Brown     }
7325552f7358SJed Brown   }
7326e6ccafaeSMatthew G Knepley   *loff += dof;
73273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7328552f7358SJed Brown }
7329552f7358SJed Brown 
73307e29afd2SMatthew G. Knepley /*
733136fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
73327e29afd2SMatthew G. Knepley 
733336fa2b79SJed Brown  Input Parameters:
733436fa2b79SJed Brown + section - a section (global or local)
733520f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
733636fa2b79SJed Brown . point - point within section
733736fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
733836fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
733936fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
734036fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
734136fa2b79SJed Brown . permsoff - offset
734236fa2b79SJed Brown - indperm - index permutation
734336fa2b79SJed Brown 
734436fa2b79SJed Brown  Output Parameter:
734536fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
734636fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
734736fa2b79SJed Brown 
734836fa2b79SJed Brown  Notes:
734936fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
735036fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
735136fa2b79SJed Brown  in the local vector.
735236fa2b79SJed Brown 
735336fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
735436fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
735536fa2b79SJed Brown 
735636fa2b79SJed Brown  Developer Note:
735736fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
735836fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
735936fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
736036fa2b79SJed Brown 
736136fa2b79SJed Brown  Example:
736236fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
736336fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
736436fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
736536fa2b79SJed 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.
736636fa2b79SJed Brown 
736736fa2b79SJed Brown  Level: developer
73687e29afd2SMatthew G. Knepley */
7369d71ae5a4SJacob 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[])
7370d71ae5a4SJacob Faibussowitsch {
7371552f7358SJed Brown   PetscInt numFields, foff, f;
7372552f7358SJed Brown 
7373552f7358SJed Brown   PetscFunctionBegin;
737408401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7376552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
73774acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7378552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
73794acb8e1eSToby Isaac     PetscInt        cind = 0, b;
73804acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7381552f7358SJed Brown 
73829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
73839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7384552f7358SJed Brown     if (!cfdof || setBC) {
738505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
738605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
738705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
738805586334SMatthew G. Knepley 
738905586334SMatthew G. Knepley         indices[ind] = off + foff + b;
739005586334SMatthew G. Knepley       }
7391552f7358SJed Brown     } else {
73929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
739305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
739405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
739505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
739605586334SMatthew G. Knepley 
73974acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
739805586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7399552f7358SJed Brown           ++cind;
7400552f7358SJed Brown         } else {
740136fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7402552f7358SJed Brown         }
7403552f7358SJed Brown       }
7404552f7358SJed Brown     }
740536fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7406552f7358SJed Brown     foffs[f] += fdof;
7407552f7358SJed Brown   }
74083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7409552f7358SJed Brown }
7410552f7358SJed Brown 
74117e29afd2SMatthew G. Knepley /*
74127e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
74137e29afd2SMatthew G. Knepley 
74147e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7415645102dcSJed Brown 
7416645102dcSJed Brown  Notes:
7417645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7418645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
74197e29afd2SMatthew G. Knepley */
7420d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7421d71ae5a4SJacob Faibussowitsch {
74227e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
74237e29afd2SMatthew G. Knepley 
74247e29afd2SMatthew G. Knepley   PetscFunctionBegin;
74259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
74267e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
74277e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
74287e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
74297e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
74307e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
74317e29afd2SMatthew G. Knepley 
74329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
74339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
74349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7435645102dcSJed Brown     if (!cfdof) {
743605586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
743705586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
743805586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
743905586334SMatthew G. Knepley 
744005586334SMatthew G. Knepley         indices[ind] = foff + b;
744105586334SMatthew G. Knepley       }
74427e29afd2SMatthew G. Knepley     } else {
74439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
744405586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
744505586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
744605586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
744705586334SMatthew G. Knepley 
74487e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
744905586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
74507e29afd2SMatthew G. Knepley           ++cind;
74517e29afd2SMatthew G. Knepley         } else {
745205586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
74537e29afd2SMatthew G. Knepley         }
74547e29afd2SMatthew G. Knepley       }
74557e29afd2SMatthew G. Knepley     }
74567e29afd2SMatthew G. Knepley     foffs[f] += fdof;
74577e29afd2SMatthew G. Knepley   }
74583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74597e29afd2SMatthew G. Knepley }
74607e29afd2SMatthew G. Knepley 
7461d71ae5a4SJacob 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)
7462d71ae5a4SJacob Faibussowitsch {
7463d3d1a6afSToby Isaac   Mat             cMat;
7464d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7465d3d1a6afSToby Isaac   IS              aIS;
7466d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7467d3d1a6afSToby Isaac   const PetscInt *anchors;
7468e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7469d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7470d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7471d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7472d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7473d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7474d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7475d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
74766ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7477d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7478d3d1a6afSToby Isaac 
7479d3d1a6afSToby Isaac   PetscFunctionBegin;
7480d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7481d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
74829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7483d3d1a6afSToby Isaac 
74849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7485d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7486d3d1a6afSToby Isaac   if (aSec) {
74879566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
74889566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
74899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7490d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7491d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7492d3d1a6afSToby Isaac      * into the global matrix anyway) */
7493d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7494d3d1a6afSToby Isaac       PetscInt b    = points[p];
74954b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7496d3d1a6afSToby Isaac 
74979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7498ad540459SPierre Jolivet       if (!bSecDof) continue;
749948a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7500d3d1a6afSToby Isaac       if (bDof) {
7501d3d1a6afSToby Isaac         /* this point is constrained */
7502d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7503d3d1a6afSToby Isaac         PetscInt bOff, q;
7504d3d1a6afSToby Isaac 
7505d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7506d3d1a6afSToby Isaac         newNumPoints += bDof;
75079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7508d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7509d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7510d3d1a6afSToby Isaac           PetscInt aDof;
7511d3d1a6afSToby Isaac 
75129566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7513d3d1a6afSToby Isaac           newNumIndices += aDof;
7514d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7515d3d1a6afSToby Isaac             PetscInt fDof;
7516d3d1a6afSToby Isaac 
75179566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7518d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7519d3d1a6afSToby Isaac           }
7520d3d1a6afSToby Isaac         }
75219371c9d4SSatish Balay       } else {
7522d3d1a6afSToby Isaac         /* this point is not constrained */
7523d3d1a6afSToby Isaac         newNumPoints++;
75244b2f2278SToby Isaac         newNumIndices += bSecDof;
7525d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7526d3d1a6afSToby Isaac           PetscInt fDof;
7527d3d1a6afSToby Isaac 
75289566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7529d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7530d3d1a6afSToby Isaac         }
7531d3d1a6afSToby Isaac       }
7532d3d1a6afSToby Isaac     }
7533d3d1a6afSToby Isaac   }
7534d3d1a6afSToby Isaac   if (!anyConstrained) {
753572b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
753672b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
753772b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
753872b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
75399566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
75403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7541d3d1a6afSToby Isaac   }
7542d3d1a6afSToby Isaac 
75436ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
75446ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
75456ecaa68aSToby Isaac 
7546f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7547d3d1a6afSToby Isaac 
75486ecaa68aSToby Isaac   if (!outPoints && !outValues) {
75496ecaa68aSToby Isaac     if (offsets) {
7550ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
75516ecaa68aSToby Isaac     }
75529566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
75533ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
75546ecaa68aSToby Isaac   }
75556ecaa68aSToby Isaac 
75561dca8a05SBarry 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);
7557d3d1a6afSToby Isaac 
75589566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7559d3d1a6afSToby Isaac 
7560d3d1a6afSToby Isaac   /* workspaces */
7561d3d1a6afSToby Isaac   if (numFields) {
7562d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
75639566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
75649566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7565d3d1a6afSToby Isaac     }
75669371c9d4SSatish Balay   } else {
75679566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
75689566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7569d3d1a6afSToby Isaac   }
7570d3d1a6afSToby Isaac 
7571d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7572d3d1a6afSToby Isaac   if (numFields) {
75734b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
75744b2f2278SToby Isaac 
7575d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7576d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
75774b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7578d3d1a6afSToby Isaac 
75799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
75804b2f2278SToby Isaac       if (!bSecDof) {
75814b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
75824b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
75834b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
75844b2f2278SToby Isaac         }
75854b2f2278SToby Isaac         continue;
75864b2f2278SToby Isaac       }
758748a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7588d3d1a6afSToby Isaac       if (bDof) {
7589d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7590d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7591d3d1a6afSToby Isaac 
75929566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
75939566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7594d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7595d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7596d3d1a6afSToby Isaac             PetscInt aFDof;
7597d3d1a6afSToby Isaac 
75989566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7599d3d1a6afSToby Isaac             allFDof += aFDof;
7600d3d1a6afSToby Isaac           }
7601d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7602d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7603d3d1a6afSToby Isaac         }
76049371c9d4SSatish Balay       } else {
7605d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7606d3d1a6afSToby Isaac           PetscInt fDof;
7607d3d1a6afSToby Isaac 
76089566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7609d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7610d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7611d3d1a6afSToby Isaac         }
7612d3d1a6afSToby Isaac       }
7613d3d1a6afSToby Isaac     }
76144b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
76154b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
76164b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7617d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7618d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7619d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7620d3d1a6afSToby Isaac       }
762119f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
762219f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
76239566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7624d3d1a6afSToby Isaac     }
76259371c9d4SSatish Balay   } else {
7626d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7627d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
76284b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7629d3d1a6afSToby Isaac 
76309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
76314b2f2278SToby Isaac       if (!bSecDof) {
76324b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
76334b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
76344b2f2278SToby Isaac         continue;
76354b2f2278SToby Isaac       }
763648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7637d3d1a6afSToby Isaac       if (bDof) {
76384b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7639d3d1a6afSToby Isaac 
76409566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7641d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7642d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7643d3d1a6afSToby Isaac 
76449566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7645d3d1a6afSToby Isaac           allDof += aDof;
7646d3d1a6afSToby Isaac         }
7647d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
76484b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
76499371c9d4SSatish Balay       } else {
76504b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7651d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7652d3d1a6afSToby Isaac       }
7653d3d1a6afSToby Isaac     }
7654d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7655d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7656d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7657d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7658d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7659d3d1a6afSToby Isaac     }
76609566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7661d3d1a6afSToby Isaac   }
7662d3d1a6afSToby Isaac 
76636ecaa68aSToby Isaac   /* output arrays */
76649566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
76656ecaa68aSToby Isaac 
7666d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
76679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
76689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
76699566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
76709566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7671d3d1a6afSToby Isaac   if (numFields) {
7672d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7673d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7674d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
76754b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7676d3d1a6afSToby Isaac 
76779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7678ad540459SPierre Jolivet       if (!bSecDof) continue;
767948a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7680d3d1a6afSToby Isaac       if (bDof) {
7681d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7682d3d1a6afSToby Isaac 
7683d3d1a6afSToby Isaac         fStart[0] = 0;
7684d3d1a6afSToby Isaac         fEnd[0]   = 0;
7685d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7686d3d1a6afSToby Isaac           PetscInt fDof;
7687d3d1a6afSToby Isaac 
76889566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7689d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7690d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7691d3d1a6afSToby Isaac         }
76929566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
76939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7694d3d1a6afSToby Isaac 
7695d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7696d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7697d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7698d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7699d3d1a6afSToby Isaac 
7700d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7701d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7702d3d1a6afSToby Isaac         }
77039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7704d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7705d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7706d3d1a6afSToby Isaac 
7707d3d1a6afSToby 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 */
7708d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7709d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
77109566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
77119566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7712d3d1a6afSToby Isaac         }
7713d3d1a6afSToby Isaac         newP += bDof;
7714d3d1a6afSToby Isaac 
77156ecaa68aSToby Isaac         if (outValues) {
7716d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
771748a46eb9SPierre 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]));
7718d3d1a6afSToby Isaac         }
77199371c9d4SSatish Balay       } else {
7720d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7721d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7722d3d1a6afSToby Isaac         newP++;
7723d3d1a6afSToby Isaac       }
7724d3d1a6afSToby Isaac     }
7725d3d1a6afSToby Isaac   } else {
7726d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7727d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7728d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
77294b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7730d3d1a6afSToby Isaac 
77319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7732ad540459SPierre Jolivet       if (!bSecDof) continue;
773348a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7734d3d1a6afSToby Isaac       if (bDof) {
7735d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7736d3d1a6afSToby Isaac 
77379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
77389566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7739d3d1a6afSToby Isaac 
77409566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7741d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7742d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7743d3d1a6afSToby Isaac 
7744d3d1a6afSToby 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 */
7745d3d1a6afSToby Isaac 
7746d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7747d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
77489566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
77499566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7750d3d1a6afSToby Isaac         }
7751d3d1a6afSToby Isaac         newP += bDof;
7752d3d1a6afSToby Isaac 
7753d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
775448a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
77559371c9d4SSatish Balay       } else {
7756d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7757d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7758d3d1a6afSToby Isaac         newP++;
7759d3d1a6afSToby Isaac       }
7760d3d1a6afSToby Isaac     }
7761d3d1a6afSToby Isaac   }
7762d3d1a6afSToby Isaac 
77636ecaa68aSToby Isaac   if (outValues) {
77649566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
77659566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7766d3d1a6afSToby Isaac     /* multiply constraints on the right */
7767d3d1a6afSToby Isaac     if (numFields) {
7768d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7769d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7770d3d1a6afSToby Isaac 
7771d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7772d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7773d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7774d3d1a6afSToby Isaac           PetscInt c, r, k;
7775d3d1a6afSToby Isaac           PetscInt dof;
7776d3d1a6afSToby Isaac 
77779566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7778ad540459SPierre Jolivet           if (!dof) continue;
7779d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7780d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7781d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7782d3d1a6afSToby Isaac 
7783d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7784d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7785ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7786d3d1a6afSToby Isaac               }
7787d3d1a6afSToby Isaac             }
77889371c9d4SSatish Balay           } else {
7789d3d1a6afSToby Isaac             /* copy this column as is */
7790d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7791ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7792d3d1a6afSToby Isaac             }
7793d3d1a6afSToby Isaac           }
7794d3d1a6afSToby Isaac           oldOff += dof;
7795d3d1a6afSToby Isaac         }
7796d3d1a6afSToby Isaac       }
77979371c9d4SSatish Balay     } else {
7798d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7799d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7800d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7801d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7802d3d1a6afSToby Isaac         PetscInt c, r, k;
7803d3d1a6afSToby Isaac         PetscInt dof;
7804d3d1a6afSToby Isaac 
78059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7806ad540459SPierre Jolivet         if (!dof) continue;
7807d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7808d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7809d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7810d3d1a6afSToby Isaac 
7811d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7812d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7813ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7814d3d1a6afSToby Isaac             }
7815d3d1a6afSToby Isaac           }
78169371c9d4SSatish Balay         } else {
7817d3d1a6afSToby Isaac           /* copy this column as is */
7818d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7819ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7820d3d1a6afSToby Isaac           }
7821d3d1a6afSToby Isaac         }
7822d3d1a6afSToby Isaac         oldOff += dof;
7823d3d1a6afSToby Isaac       }
7824d3d1a6afSToby Isaac     }
7825d3d1a6afSToby Isaac 
78266ecaa68aSToby Isaac     if (multiplyLeft) {
78279566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
78289566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7829d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7830d3d1a6afSToby Isaac       if (numFields) {
7831d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7832d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7833d3d1a6afSToby Isaac 
7834d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7835d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7836d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7837d3d1a6afSToby Isaac             PetscInt c, r, k;
7838d3d1a6afSToby Isaac             PetscInt dof;
7839d3d1a6afSToby Isaac 
78409566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7841d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7842d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7843d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7844d3d1a6afSToby Isaac 
7845d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7846d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7847ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7848d3d1a6afSToby Isaac                 }
7849d3d1a6afSToby Isaac               }
78509371c9d4SSatish Balay             } else {
7851d3d1a6afSToby Isaac               /* copy this row as is */
7852d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7853ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7854d3d1a6afSToby Isaac               }
7855d3d1a6afSToby Isaac             }
7856d3d1a6afSToby Isaac             oldOff += dof;
7857d3d1a6afSToby Isaac           }
7858d3d1a6afSToby Isaac         }
78599371c9d4SSatish Balay       } else {
7860d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7861d3d1a6afSToby Isaac 
7862d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7863d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7864d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7865d3d1a6afSToby Isaac           PetscInt c, r, k;
7866d3d1a6afSToby Isaac           PetscInt dof;
7867d3d1a6afSToby Isaac 
78689566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7869d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7870d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7871d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7872d3d1a6afSToby Isaac 
7873d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7874d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7875ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7876d3d1a6afSToby Isaac               }
7877d3d1a6afSToby Isaac             }
78789371c9d4SSatish Balay           } else {
7879d3d1a6afSToby Isaac             /* copy this row as is */
78809fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7881ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7882d3d1a6afSToby Isaac             }
7883d3d1a6afSToby Isaac           }
7884d3d1a6afSToby Isaac           oldOff += dof;
7885d3d1a6afSToby Isaac         }
7886d3d1a6afSToby Isaac       }
7887d3d1a6afSToby Isaac 
78889566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
78899371c9d4SSatish Balay     } else {
78906ecaa68aSToby Isaac       newValues = tmpValues;
78916ecaa68aSToby Isaac     }
78926ecaa68aSToby Isaac   }
78936ecaa68aSToby Isaac 
7894d3d1a6afSToby Isaac   /* clean up */
78959566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
78969566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
78976ecaa68aSToby Isaac 
7898d3d1a6afSToby Isaac   if (numFields) {
7899d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
79009566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
79019566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
79029566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7903d3d1a6afSToby Isaac     }
79049371c9d4SSatish Balay   } else {
79059566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
79069566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
79079566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7908d3d1a6afSToby Isaac   }
79099566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7910d3d1a6afSToby Isaac 
7911d3d1a6afSToby Isaac   /* output */
79126ecaa68aSToby Isaac   if (outPoints) {
7913d3d1a6afSToby Isaac     *outPoints = newPoints;
79149371c9d4SSatish Balay   } else {
79159566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
79166ecaa68aSToby Isaac   }
7917ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7918ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
79193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7920d3d1a6afSToby Isaac }
7921d3d1a6afSToby Isaac 
79224a1e0b3eSMatthew G. Knepley /*@C
792371f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
79247cd05799SMatthew G. Knepley 
79257cd05799SMatthew G. Knepley   Not collective
79267cd05799SMatthew G. Knepley 
79277cd05799SMatthew G. Knepley   Input Parameters:
7928a1cb98faSBarry Smith + dm         - The `DM`
7929a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7930a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
793171f0bbf9SMatthew G. Knepley . point      - The point defining the closure
793271f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
79337cd05799SMatthew G. Knepley 
793471f0bbf9SMatthew G. Knepley   Output Parameters:
793571f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
793671f0bbf9SMatthew G. Knepley . indices    - The dof indices
793720f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
793820f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
79397cd05799SMatthew G. Knepley 
7940a1cb98faSBarry Smith   Level: advanced
794136fa2b79SJed Brown 
7942a1cb98faSBarry Smith   Notes:
7943a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7944a1cb98faSBarry Smith 
794520f4b53cSBarry Smith   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
794620f4b53cSBarry Smith   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
794736fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
794820f4b53cSBarry Smith   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
794936fa2b79SJed Brown   indices (with the above semantics) are implied.
79507cd05799SMatthew G. Knepley 
79511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7952a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
79534a1e0b3eSMatthew G. Knepley @*/
7954d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7955d71ae5a4SJacob Faibussowitsch {
795671f0bbf9SMatthew G. Knepley   /* Closure ordering */
79577773e69fSMatthew G. Knepley   PetscSection    clSection;
79587773e69fSMatthew G. Knepley   IS              clPoints;
795971f0bbf9SMatthew G. Knepley   const PetscInt *clp;
796071f0bbf9SMatthew G. Knepley   PetscInt       *points;
796171f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
796271f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
79634acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
796471f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
796571f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
796671f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
796771f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
796871f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
796971f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
797071f0bbf9SMatthew G. Knepley 
797171f0bbf9SMatthew G. Knepley   PetscInt *idx;
797271f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
797371f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
79747773e69fSMatthew G. Knepley 
797571f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
79767773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79777773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
797836fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
79794f572ea9SToby Isaac   if (numIndices) PetscAssertPointer(numIndices, 6);
79804f572ea9SToby Isaac   if (indices) PetscAssertPointer(indices, 7);
79814f572ea9SToby Isaac   if (outOffsets) PetscAssertPointer(outOffsets, 8);
79824f572ea9SToby Isaac   if (values) PetscAssertPointer(values, 9);
79839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
798463a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
79859566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
798671f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
798707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7988c459fbc1SJed Brown   if (useClPerm) {
7989c459fbc1SJed Brown     PetscInt depth, clsize;
79909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7991c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7992c459fbc1SJed Brown       PetscInt dof;
79939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7994c459fbc1SJed Brown       clsize += dof;
7995c459fbc1SJed Brown     }
79969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7997c459fbc1SJed Brown   }
799871f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
799971f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
80007773e69fSMatthew G. Knepley     PetscInt dof, fdof;
80017773e69fSMatthew G. Knepley 
80029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
80037773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
80049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
80057773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
80067773e69fSMatthew G. Knepley     }
800771f0bbf9SMatthew G. Knepley     Ni += dof;
80087773e69fSMatthew G. Knepley   }
80097773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
80101dca8a05SBarry 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);
801171f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
801271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
80139566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
80149566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
801571f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
801671f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
801771f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
80186ecaa68aSToby Isaac 
801971f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
802071f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
802171f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
802271f0bbf9SMatthew G. Knepley 
80239566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
80249566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
802571f0bbf9SMatthew G. Knepley         if (flip) {
802671f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
802771f0bbf9SMatthew G. Knepley 
802871f0bbf9SMatthew G. Knepley           if (!valCopy) {
80299566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
803071f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
803171f0bbf9SMatthew G. Knepley             *values = valCopy;
803271f0bbf9SMatthew G. Knepley           }
803371f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
803471f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
803571f0bbf9SMatthew G. Knepley 
803671f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
803771f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
803871f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
80396ecaa68aSToby Isaac             }
80406ecaa68aSToby Isaac           }
804171f0bbf9SMatthew G. Knepley         }
804271f0bbf9SMatthew G. Knepley         foffset += fdof;
804371f0bbf9SMatthew G. Knepley       }
804471f0bbf9SMatthew G. Knepley     }
804571f0bbf9SMatthew G. Knepley   }
804671f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
80479566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
804871f0bbf9SMatthew G. Knepley   if (NclC) {
80499566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
805071f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
80519566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
80529566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
805371f0bbf9SMatthew G. Knepley     }
805471f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
80559566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
80569566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
805771f0bbf9SMatthew G. Knepley     }
80589566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
805971f0bbf9SMatthew G. Knepley     Ncl    = NclC;
806071f0bbf9SMatthew G. Knepley     Ni     = NiC;
806171f0bbf9SMatthew G. Knepley     points = pointsC;
806271f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
806371f0bbf9SMatthew G. Knepley   }
806471f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
80659566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
806671f0bbf9SMatthew G. Knepley   if (Nf) {
806771f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
806871f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
806971f0bbf9SMatthew G. Knepley 
80709371c9d4SSatish Balay     if (outOffsets) {
80719371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
80729371c9d4SSatish Balay     }
80739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
807471f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
807571f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
807671f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
807771f0bbf9SMatthew G. Knepley 
80789566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
80797773e69fSMatthew G. Knepley       }
80807773e69fSMatthew G. Knepley     } else {
808171f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
808271f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
808371f0bbf9SMatthew G. Knepley 
80849566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
808571f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
808671f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
808771f0bbf9SMatthew G. Knepley          * global section. */
80889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
808971f0bbf9SMatthew G. Knepley       }
809071f0bbf9SMatthew G. Knepley     }
809171f0bbf9SMatthew G. Knepley   } else {
809271f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
809371f0bbf9SMatthew G. Knepley 
809471f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
809571f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
80964acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
80974acb8e1eSToby Isaac 
80989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
809971f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
810071f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
81019566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
81027773e69fSMatthew G. Knepley     }
81037773e69fSMatthew G. Knepley   }
810471f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
810571f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
81069566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
81079566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
81084acb8e1eSToby Isaac   }
810971f0bbf9SMatthew G. Knepley   if (NclC) {
81109566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
81117773e69fSMatthew G. Knepley   } else {
81129566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
81137773e69fSMatthew G. Knepley   }
811471f0bbf9SMatthew G. Knepley 
811571f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
811671f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
81173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81187773e69fSMatthew G. Knepley }
81197773e69fSMatthew G. Knepley 
81207cd05799SMatthew G. Knepley /*@C
812171f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
81227cd05799SMatthew G. Knepley 
81237cd05799SMatthew G. Knepley   Not collective
81247cd05799SMatthew G. Knepley 
81257cd05799SMatthew G. Knepley   Input Parameters:
8126a1cb98faSBarry Smith + dm         - The `DM`
8127a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
8128a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
812971f0bbf9SMatthew G. Knepley . point      - The point defining the closure
813071f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
813171f0bbf9SMatthew G. Knepley 
813271f0bbf9SMatthew G. Knepley   Output Parameters:
813371f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
813471f0bbf9SMatthew G. Knepley . indices    - The dof indices
813520f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
813620f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
813771f0bbf9SMatthew G. Knepley 
8138a1cb98faSBarry Smith   Level: advanced
813971f0bbf9SMatthew G. Knepley 
8140a1cb98faSBarry Smith   Notes:
8141a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
8142a1cb98faSBarry Smith 
8143a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
814471f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
814571f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
814671f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
814771f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
81487cd05799SMatthew G. Knepley 
81491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
81507cd05799SMatthew G. Knepley @*/
8151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8152d71ae5a4SJacob Faibussowitsch {
81537773e69fSMatthew G. Knepley   PetscFunctionBegin;
81547773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81554f572ea9SToby Isaac   PetscAssertPointer(indices, 7);
81569566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
81573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81587773e69fSMatthew G. Knepley }
81597773e69fSMatthew G. Knepley 
8160e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8161d71ae5a4SJacob Faibussowitsch {
8162552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
8163552f7358SJed Brown   PetscInt          *indices;
816471f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
816571f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
8166552f7358SJed Brown   PetscErrorCode     ierr;
8167552f7358SJed Brown 
8168552f7358SJed Brown   PetscFunctionBegin;
8169552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81709566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
81713dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
81729566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
81733dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
8174e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 5);
8175552f7358SJed Brown 
8176e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values));
81770d644c17SKarl Rupp 
81789566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
8179d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
81804a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
8181552f7358SJed Brown   if (ierr) {
8182552f7358SJed Brown     PetscMPIInt rank;
8183552f7358SJed Brown 
81849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81859566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81869566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
81879566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81889566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
8189c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
8190552f7358SJed Brown   }
81914a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
81924a1e0b3eSMatthew G. Knepley     PetscInt i;
81939566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
819463a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
81959566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
81964a1e0b3eSMatthew G. Knepley   }
819771f0bbf9SMatthew G. Knepley 
81989566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81999566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
82003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82014acb8e1eSToby Isaac }
820271f0bbf9SMatthew G. Knepley 
82034a1e0b3eSMatthew G. Knepley /*@C
8204e8e188d2SZach Atkins   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
8205e8e188d2SZach Atkins 
8206e8e188d2SZach Atkins   Not collective
8207e8e188d2SZach Atkins 
8208e8e188d2SZach Atkins   Input Parameters:
8209e8e188d2SZach Atkins + dm            - The `DM`
8210e8e188d2SZach Atkins . section       - The section describing the layout in `v`, or `NULL` to use the default section
8211e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
8212e8e188d2SZach Atkins . A             - The matrix
8213e8e188d2SZach Atkins . point         - The point in the `DM`
8214e8e188d2SZach Atkins . values        - The array of values
8215e8e188d2SZach Atkins - mode          - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
8216e8e188d2SZach Atkins 
8217e8e188d2SZach Atkins   Level: intermediate
8218e8e188d2SZach Atkins 
8219e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
8220e8e188d2SZach Atkins @*/
8221e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8222e8e188d2SZach Atkins {
8223e8e188d2SZach Atkins   PetscFunctionBegin;
8224e8e188d2SZach Atkins   PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode));
8225e8e188d2SZach Atkins   PetscFunctionReturn(PETSC_SUCCESS);
8226e8e188d2SZach Atkins }
8227e8e188d2SZach Atkins 
8228e8e188d2SZach Atkins /*@C
822960225df5SJacob Faibussowitsch   DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section
82304a1e0b3eSMatthew G. Knepley 
82314a1e0b3eSMatthew G. Knepley   Not collective
82324a1e0b3eSMatthew G. Knepley 
82334a1e0b3eSMatthew G. Knepley   Input Parameters:
8234a1cb98faSBarry Smith + dmRow            - The `DM` for the row fields
823520f4b53cSBarry Smith . sectionRow       - The section describing the layout, or `NULL` to use the default section in `dmRow`
8236e8e188d2SZach Atkins . useRowPerm       - The flag to use the closure permutation of the `dmRow` if available
823720f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
8238a1cb98faSBarry Smith . dmCol            - The `DM` for the column fields
823920f4b53cSBarry Smith . sectionCol       - The section describing the layout, or `NULL` to use the default section in `dmCol`
8240e8e188d2SZach Atkins . useColPerm       - The flag to use the closure permutation of the `dmCol` if available
824120f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
82424a1e0b3eSMatthew G. Knepley . A                - The matrix
8243a1cb98faSBarry Smith . point            - The point in the `DM`
82444a1e0b3eSMatthew G. Knepley . values           - The array of values
8245a1cb98faSBarry Smith - mode             - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
82464a1e0b3eSMatthew G. Knepley 
82474a1e0b3eSMatthew G. Knepley   Level: intermediate
82484a1e0b3eSMatthew G. Knepley 
82491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
82504a1e0b3eSMatthew G. Knepley @*/
8251e8e188d2SZach 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)
8252d71ae5a4SJacob Faibussowitsch {
825371f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
825471f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
825571f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
825671f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
825771f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
825871f0bbf9SMatthew G. Knepley 
825971f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
826071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
82619566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
826271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
82639566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
826471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
8265e8e188d2SZach Atkins   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5);
82669566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
8267e8e188d2SZach Atkins   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6);
82689566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
8269e8e188d2SZach Atkins   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7);
8270e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 9);
827171f0bbf9SMatthew G. Knepley 
8272e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
8273e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
827471f0bbf9SMatthew G. Knepley 
82759566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
8276d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
82774a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
827871f0bbf9SMatthew G. Knepley   if (ierr) {
827971f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
828071f0bbf9SMatthew G. Knepley 
82819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
82829566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
82839566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
82849566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
82859566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
82869566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
8287d3d1a6afSToby Isaac   }
828871f0bbf9SMatthew G. Knepley 
8289e8e188d2SZach Atkins   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
8290e8e188d2SZach Atkins   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
82919566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
82923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8293552f7358SJed Brown }
8294552f7358SJed Brown 
8295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8296d71ae5a4SJacob Faibussowitsch {
8297de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
8298de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
8299de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
8300de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
830117c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8302de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
8303412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
83044ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
8305de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
8306de41b84cSMatthew G. Knepley 
8307de41b84cSMatthew G. Knepley   PetscFunctionBegin;
8308de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
8309de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
83109566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
8311de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
83129566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
8313de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
83149566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
8315de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
83169566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
8317de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
8318de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
83199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
832063a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
83219566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
83229566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
8323de41b84cSMatthew G. Knepley   /* Column indices */
83249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
83254ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
8326de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
8327de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
83289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8329de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8330de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8331de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8332de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8333de41b84cSMatthew G. Knepley       ++q;
8334de41b84cSMatthew G. Knepley     }
8335de41b84cSMatthew G. Knepley   }
8336de41b84cSMatthew G. Knepley   numCPoints = q;
8337de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8338de41b84cSMatthew G. Knepley     PetscInt fdof;
8339de41b84cSMatthew G. Knepley 
83409566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
83414ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8342de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8344de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8345de41b84cSMatthew G. Knepley     }
8346de41b84cSMatthew G. Knepley     numCIndices += dof;
8347de41b84cSMatthew G. Knepley   }
8348de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8349de41b84cSMatthew G. Knepley   /* Row indices */
83509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8351412e9a14SMatthew G. Knepley   {
8352012bc364SMatthew G. Knepley     DMPlexTransform tr;
8353012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8354012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8355012bc364SMatthew G. Knepley 
83569566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
83579566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
83589566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8359012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
83609566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8361412e9a14SMatthew G. Knepley   }
83629566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8363de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8364de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
83659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8366de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
83679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8368de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8369de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
83709566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
83714ca5e9f5SMatthew G. Knepley         if (!dof) continue;
83729371c9d4SSatish Balay         for (s = 0; s < q; ++s)
83739371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
83744ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8375de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8376de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8377de41b84cSMatthew G. Knepley         ++q;
8378de41b84cSMatthew G. Knepley       }
8379de41b84cSMatthew G. Knepley     }
83809566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8381de41b84cSMatthew G. Knepley   }
8382de41b84cSMatthew G. Knepley   numFPoints = q;
8383de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8384de41b84cSMatthew G. Knepley     PetscInt fdof;
8385de41b84cSMatthew G. Knepley 
83869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
83874ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8388de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8390de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8391de41b84cSMatthew G. Knepley     }
8392de41b84cSMatthew G. Knepley     numFIndices += dof;
8393de41b84cSMatthew G. Knepley   }
8394de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8395de41b84cSMatthew G. Knepley 
83961dca8a05SBarry 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);
83971dca8a05SBarry 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);
83989566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83999566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8400de41b84cSMatthew G. Knepley   if (numFields) {
84014acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
84024acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
84034acb8e1eSToby Isaac 
84044acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8407de41b84cSMatthew G. Knepley     }
84084acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
84099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84109566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
84114acb8e1eSToby Isaac     }
84124acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
84139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
84154acb8e1eSToby Isaac     }
84164acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84179566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84189566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8419de41b84cSMatthew G. Knepley     }
8420de41b84cSMatthew G. Knepley   } else {
84214acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
84224acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
84234acb8e1eSToby Isaac 
84249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
84259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
84264acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
84274acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
84284acb8e1eSToby Isaac 
84299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8431de41b84cSMatthew G. Knepley     }
84324acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
84334acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
84344acb8e1eSToby Isaac 
84359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8437de41b84cSMatthew G. Knepley     }
84389566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
84399566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8440de41b84cSMatthew G. Knepley   }
84419566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
84424acb8e1eSToby Isaac   /* TODO: flips */
8443d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8444de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8445de41b84cSMatthew G. Knepley   if (ierr) {
8446de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8447de41b84cSMatthew G. Knepley 
84489566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
84499566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
84509566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
84519566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
84529566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8453de41b84cSMatthew G. Knepley   }
84549566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
84559566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84569566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
84579566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
84583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8459de41b84cSMatthew G. Knepley }
8460de41b84cSMatthew G. Knepley 
8461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8462d71ae5a4SJacob Faibussowitsch {
84637c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
84647c927364SMatthew G. Knepley   PetscInt       *cpoints      = NULL;
8465230af79eSStefano Zampini   PetscInt        foffsets[32] = {0}, coffsets[32] = {0};
846617c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8467412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
84687c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
84697c927364SMatthew G. Knepley 
84707c927364SMatthew G. Knepley   PetscFunctionBegin;
84717c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
84727c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
84739566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
84747c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
84759566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
84767c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
84779566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
84787c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
84799566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
84807c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
84819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
848263a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
84837c927364SMatthew G. Knepley   /* Column indices */
84849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84857c927364SMatthew G. Knepley   maxFPoints = numCPoints;
84867c927364SMatthew G. Knepley   /* Compress out points not in the section */
84877c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
84889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
84897c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
84907c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
84917c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
84927c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
84937c927364SMatthew G. Knepley       ++q;
84947c927364SMatthew G. Knepley     }
84957c927364SMatthew G. Knepley   }
84967c927364SMatthew G. Knepley   numCPoints = q;
84977c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
84987c927364SMatthew G. Knepley     PetscInt fdof;
84997c927364SMatthew G. Knepley 
85009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
85017c927364SMatthew G. Knepley     if (!dof) continue;
85027c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
85039566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
85047c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
85057c927364SMatthew G. Knepley     }
85067c927364SMatthew G. Knepley     numCIndices += dof;
85077c927364SMatthew G. Knepley   }
85087c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
85097c927364SMatthew G. Knepley   /* Row indices */
85109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8511412e9a14SMatthew G. Knepley   {
8512012bc364SMatthew G. Knepley     DMPlexTransform tr;
8513012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8514012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8515012bc364SMatthew G. Knepley 
85169566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
85179566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
85189566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8519012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
85209566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8521412e9a14SMatthew G. Knepley   }
85229566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
85237c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
85247c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
85259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
85267c927364SMatthew G. Knepley     /* Compress out points not in the section */
85279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
85287c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
85297c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
85309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
85317c927364SMatthew G. Knepley         if (!dof) continue;
85329371c9d4SSatish Balay         for (s = 0; s < q; ++s)
85339371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
85347c927364SMatthew G. Knepley         if (s < q) continue;
85357c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
85367c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
85377c927364SMatthew G. Knepley         ++q;
85387c927364SMatthew G. Knepley       }
85397c927364SMatthew G. Knepley     }
85409566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
85417c927364SMatthew G. Knepley   }
85427c927364SMatthew G. Knepley   numFPoints = q;
85437c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
85447c927364SMatthew G. Knepley     PetscInt fdof;
85457c927364SMatthew G. Knepley 
85469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
85477c927364SMatthew G. Knepley     if (!dof) continue;
85487c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
85499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
85507c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
85517c927364SMatthew G. Knepley     }
85527c927364SMatthew G. Knepley     numFIndices += dof;
85537c927364SMatthew G. Knepley   }
85547c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
85557c927364SMatthew G. Knepley 
85561dca8a05SBarry 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);
85571dca8a05SBarry 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);
85587c927364SMatthew G. Knepley   if (numFields) {
85594acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
85604acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
85614acb8e1eSToby Isaac 
85624acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
85639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
85649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
85657c927364SMatthew G. Knepley     }
85664acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
85679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
85689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
85694acb8e1eSToby Isaac     }
85704acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
85719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85729566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
85734acb8e1eSToby Isaac     }
85744acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
85759566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
85769566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
85777c927364SMatthew G. Knepley     }
85787c927364SMatthew G. Knepley   } else {
85794acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
85804acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
85814acb8e1eSToby Isaac 
85829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85844acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
85854acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
85864acb8e1eSToby Isaac 
85879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
85889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
85897c927364SMatthew G. Knepley     }
85904acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
85914acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
85924acb8e1eSToby Isaac 
85939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
85957c927364SMatthew G. Knepley     }
85969566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85979566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85987c927364SMatthew G. Knepley   }
85999566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
86009566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
86013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86027c927364SMatthew G. Knepley }
86037c927364SMatthew G. Knepley 
86047cd05799SMatthew G. Knepley /*@C
86057cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
86067cd05799SMatthew G. Knepley 
86077cd05799SMatthew G. Knepley   Input Parameter:
8608a1cb98faSBarry Smith . dm - The `DMPLEX` object
86097cd05799SMatthew G. Knepley 
86107cd05799SMatthew G. Knepley   Output Parameter:
86117cd05799SMatthew G. Knepley . cellHeight - The height of a cell
86127cd05799SMatthew G. Knepley 
86137cd05799SMatthew G. Knepley   Level: developer
86147cd05799SMatthew G. Knepley 
86151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
86167cd05799SMatthew G. Knepley @*/
8617d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8618d71ae5a4SJacob Faibussowitsch {
8619552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8620552f7358SJed Brown 
8621552f7358SJed Brown   PetscFunctionBegin;
8622552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86234f572ea9SToby Isaac   PetscAssertPointer(cellHeight, 2);
8624552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
86253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8626552f7358SJed Brown }
8627552f7358SJed Brown 
86287cd05799SMatthew G. Knepley /*@C
86297cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
86307cd05799SMatthew G. Knepley 
86317cd05799SMatthew G. Knepley   Input Parameters:
8632a1cb98faSBarry Smith + dm         - The `DMPLEX` object
86337cd05799SMatthew G. Knepley - cellHeight - The height of a cell
86347cd05799SMatthew G. Knepley 
86357cd05799SMatthew G. Knepley   Level: developer
86367cd05799SMatthew G. Knepley 
86371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
86387cd05799SMatthew G. Knepley @*/
8639d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8640d71ae5a4SJacob Faibussowitsch {
8641552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8642552f7358SJed Brown 
8643552f7358SJed Brown   PetscFunctionBegin;
8644552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8645552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
86463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8647552f7358SJed Brown }
8648552f7358SJed Brown 
8649e6139122SMatthew G. Knepley /*@
86502827ebadSStefano Zampini   DMPlexGetCellTypeStratum - Get the range of cells of a given celltype
8651e6139122SMatthew G. Knepley 
86522827ebadSStefano Zampini   Input Parameters:
86532827ebadSStefano Zampini + dm - The `DMPLEX` object
86542827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell
8655e6139122SMatthew G. Knepley 
8656e6139122SMatthew G. Knepley   Output Parameters:
86572827ebadSStefano Zampini + start - The first cell of this type, or `NULL`
86582827ebadSStefano Zampini - end   - The upper bound on this celltype, or `NULL`
8659e6139122SMatthew G. Knepley 
86602a9f31c0SMatthew G. Knepley   Level: advanced
8661e6139122SMatthew G. Knepley 
86622827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
8663e6139122SMatthew G. Knepley @*/
86642827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end)
8665d71ae5a4SJacob Faibussowitsch {
86662827ebadSStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
86672827ebadSStefano Zampini   DMLabel  label;
86682827ebadSStefano Zampini   PetscInt pStart, pEnd;
8669e6139122SMatthew G. Knepley 
8670e6139122SMatthew G. Knepley   PetscFunctionBegin;
8671e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86722827ebadSStefano Zampini   if (start) {
86734f572ea9SToby Isaac     PetscAssertPointer(start, 3);
86742827ebadSStefano Zampini     *start = 0;
86752827ebadSStefano Zampini   }
86762827ebadSStefano Zampini   if (end) {
86774f572ea9SToby Isaac     PetscAssertPointer(end, 4);
86782827ebadSStefano Zampini     *end = 0;
86792827ebadSStefano Zampini   }
86802827ebadSStefano Zampini   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
86812827ebadSStefano Zampini   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
86822827ebadSStefano Zampini   if (mesh->tr) {
86832827ebadSStefano Zampini     PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end));
86842827ebadSStefano Zampini   } else {
86852827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
86862827ebadSStefano Zampini     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found");
86872827ebadSStefano Zampini     PetscCall(DMLabelGetStratumBounds(label, ct, start, end));
86882827ebadSStefano Zampini   }
86893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8690e6139122SMatthew G. Knepley }
8691e6139122SMatthew G. Knepley 
8692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8693d71ae5a4SJacob Faibussowitsch {
8694552f7358SJed Brown   PetscSection section, globalSection;
8695552f7358SJed Brown   PetscInt    *numbers, p;
8696552f7358SJed Brown 
8697552f7358SJed Brown   PetscFunctionBegin;
8698d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
86999566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
87009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
870148a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
87029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
8703eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection));
87049566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8705552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
87069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8707ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8708ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8709552f7358SJed Brown   }
87109566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8711ef48cebcSMatthew G. Knepley   if (globalSize) {
8712ef48cebcSMatthew G. Knepley     PetscLayout layout;
87139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
87149566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
87159566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8716ef48cebcSMatthew G. Knepley   }
87179566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
87189566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
87193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8720552f7358SJed Brown }
8721552f7358SJed Brown 
8722d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8723d71ae5a4SJacob Faibussowitsch {
8724412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8725552f7358SJed Brown 
8726552f7358SJed Brown   PetscFunctionBegin;
87279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87289566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
87299566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
87309566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
87313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8732552f7358SJed Brown }
873381ed3555SMatthew G. Knepley 
87348dab3259SMatthew G. Knepley /*@
87357cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
87367cd05799SMatthew G. Knepley 
87377cd05799SMatthew G. Knepley   Input Parameter:
8738a1cb98faSBarry Smith . dm - The `DMPLEX` object
87397cd05799SMatthew G. Knepley 
87407cd05799SMatthew G. Knepley   Output Parameter:
87417cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
87427cd05799SMatthew G. Knepley 
87437cd05799SMatthew G. Knepley   Level: developer
87447cd05799SMatthew G. Knepley 
87451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
87467cd05799SMatthew G. Knepley @*/
8747d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8748d71ae5a4SJacob Faibussowitsch {
874981ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
875081ed3555SMatthew G. Knepley 
875181ed3555SMatthew G. Knepley   PetscFunctionBegin;
875281ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87539566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8754552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
87553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8756552f7358SJed Brown }
8757552f7358SJed Brown 
8758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8759d71ae5a4SJacob Faibussowitsch {
8760412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
876181ed3555SMatthew G. Knepley 
876281ed3555SMatthew G. Knepley   PetscFunctionBegin;
876381ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
87659566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
87663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
876781ed3555SMatthew G. Knepley }
876881ed3555SMatthew G. Knepley 
87698dab3259SMatthew G. Knepley /*@
87706aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
87717cd05799SMatthew G. Knepley 
87727cd05799SMatthew G. Knepley   Input Parameter:
8773a1cb98faSBarry Smith . dm - The `DMPLEX` object
87747cd05799SMatthew G. Knepley 
87757cd05799SMatthew G. Knepley   Output Parameter:
87767cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
87777cd05799SMatthew G. Knepley 
87787cd05799SMatthew G. Knepley   Level: developer
87797cd05799SMatthew G. Knepley 
87801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87817cd05799SMatthew G. Knepley @*/
8782d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8783d71ae5a4SJacob Faibussowitsch {
8784552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8785552f7358SJed Brown 
8786552f7358SJed Brown   PetscFunctionBegin;
8787552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87889566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8789552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
87903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8791552f7358SJed Brown }
8792552f7358SJed Brown 
87938dab3259SMatthew G. Knepley /*@
8794966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8795966484cfSJed Brown 
879620f4b53cSBarry Smith   Collective
87977cd05799SMatthew G. Knepley 
87987cd05799SMatthew G. Knepley   Input Parameter:
8799a1cb98faSBarry Smith . dm - The `DMPLEX` object
88007cd05799SMatthew G. Knepley 
88017cd05799SMatthew G. Knepley   Output Parameter:
88027cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
88037cd05799SMatthew G. Knepley 
8804a1cb98faSBarry Smith   Level: developer
8805966484cfSJed Brown 
8806a1cb98faSBarry Smith   Notes:
8807a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8808966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8809966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8810966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8811966484cfSJed Brown 
8812966484cfSJed Brown   The partitioned mesh is
8813966484cfSJed Brown   ```
8814966484cfSJed Brown   (2)--0--(3)--1--(4)    (1)--0--(2)
8815966484cfSJed Brown   ```
8816966484cfSJed Brown   and its global numbering is
8817966484cfSJed Brown   ```
8818966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8819966484cfSJed Brown   ```
8820966484cfSJed Brown   Then the global numbering is provided as
8821966484cfSJed Brown   ```
8822966484cfSJed Brown   [0] Number of indices in set 5
8823966484cfSJed Brown   [0] 0 0
8824966484cfSJed Brown   [0] 1 1
8825966484cfSJed Brown   [0] 2 3
8826966484cfSJed Brown   [0] 3 4
8827966484cfSJed Brown   [0] 4 -6
8828966484cfSJed Brown   [1] Number of indices in set 3
8829966484cfSJed Brown   [1] 0 2
8830966484cfSJed Brown   [1] 1 5
8831966484cfSJed Brown   [1] 2 6
8832966484cfSJed Brown   ```
8833966484cfSJed Brown 
88341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
88357cd05799SMatthew G. Knepley @*/
8836d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8837d71ae5a4SJacob Faibussowitsch {
8838ef48cebcSMatthew G. Knepley   IS        nums[4];
8839862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8840ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
88410c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8842ef48cebcSMatthew G. Knepley 
8843ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8844ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
88460c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
88479566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
88480c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8849862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8850862913ffSStefano Zampini     PetscInt end;
8851862913ffSStefano Zampini 
8852862913ffSStefano Zampini     depths[d] = depth - d;
88539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
88540c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8855862913ffSStefano Zampini   }
88560c15888dSMatthew G. Knepley   if (empty)
88570c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
88580c15888dSMatthew G. Knepley       depths[d] = -1;
88590c15888dSMatthew G. Knepley       starts[d] = -1;
88600c15888dSMatthew G. Knepley     }
88610c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
88621c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8863ad540459SPierre 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]);
88640c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8865ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8866ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8867ef48cebcSMatthew G. Knepley 
88689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
88699566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8870ef48cebcSMatthew G. Knepley     shift += gsize;
8871ef48cebcSMatthew G. Knepley   }
8872d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
88739566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
88743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8875ef48cebcSMatthew G. Knepley }
8876ef48cebcSMatthew G. Knepley 
887708a22f4bSMatthew G. Knepley /*@
887808a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
887908a22f4bSMatthew G. Knepley 
888008a22f4bSMatthew G. Knepley   Input Parameter:
8881a1cb98faSBarry Smith . dm - The `DMPLEX` object
888208a22f4bSMatthew G. Knepley 
888308a22f4bSMatthew G. Knepley   Output Parameter:
888408a22f4bSMatthew G. Knepley . ranks - The rank field
888508a22f4bSMatthew G. Knepley 
8886a1cb98faSBarry Smith   Options Database Key:
888720f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
888808a22f4bSMatthew G. Knepley 
888908a22f4bSMatthew G. Knepley   Level: intermediate
889008a22f4bSMatthew G. Knepley 
88911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
889208a22f4bSMatthew G. Knepley @*/
8893d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8894d71ae5a4SJacob Faibussowitsch {
889508a22f4bSMatthew G. Knepley   DM             rdm;
889608a22f4bSMatthew G. Knepley   PetscFE        fe;
889708a22f4bSMatthew G. Knepley   PetscScalar   *r;
889808a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8899a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
890008a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8901a55f9a55SMatthew G. Knepley   PetscBool      simplex;
890208a22f4bSMatthew G. Knepley 
890308a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8904f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89054f572ea9SToby Isaac   PetscAssertPointer(ranks, 2);
89069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
89079566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
89089566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
89099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
89109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8911a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
89129566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
89139566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
89149566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
89159566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
89169566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
89179566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
89189566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
89199566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
892008a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
892108a22f4bSMatthew G. Knepley     PetscScalar *lr;
892208a22f4bSMatthew G. Knepley 
89239566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
892471f09efeSPierre Jolivet     if (lr) *lr = rank;
892508a22f4bSMatthew G. Knepley   }
89269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
89279566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
89283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
892908a22f4bSMatthew G. Knepley }
893008a22f4bSMatthew G. Knepley 
8931ca8062c8SMatthew G. Knepley /*@
8932acf3173eSStefano Zampini   DMPlexCreateLabelField - Create a field whose value is the label value for that point
893318e14f0cSMatthew G. Knepley 
893418e14f0cSMatthew G. Knepley   Input Parameters:
893520f4b53cSBarry Smith + dm    - The `DMPLEX`
893620f4b53cSBarry Smith - label - The `DMLabel`
893718e14f0cSMatthew G. Knepley 
893818e14f0cSMatthew G. Knepley   Output Parameter:
893918e14f0cSMatthew G. Knepley . val - The label value field
894018e14f0cSMatthew G. Knepley 
894120f4b53cSBarry Smith   Options Database Key:
894220f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
894318e14f0cSMatthew G. Knepley 
894418e14f0cSMatthew G. Knepley   Level: intermediate
894518e14f0cSMatthew G. Knepley 
89461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
894718e14f0cSMatthew G. Knepley @*/
8948d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8949d71ae5a4SJacob Faibussowitsch {
89501033741fSStefano Zampini   DM             rdm, plex;
8951acf3173eSStefano Zampini   Vec            lval;
8952acf3173eSStefano Zampini   PetscSection   section;
895318e14f0cSMatthew G. Knepley   PetscFE        fe;
895418e14f0cSMatthew G. Knepley   PetscScalar   *v;
8955acf3173eSStefano Zampini   PetscInt       dim, pStart, pEnd, p, cStart;
8956acf3173eSStefano Zampini   DMPolytopeType ct;
8957acf3173eSStefano Zampini   char           name[PETSC_MAX_PATH_LEN];
8958acf3173eSStefano Zampini   const char    *lname, *prefix;
895918e14f0cSMatthew G. Knepley 
896018e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
896118e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89624f572ea9SToby Isaac   PetscAssertPointer(label, 2);
89634f572ea9SToby Isaac   PetscAssertPointer(val, 3);
89649566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
8965acf3173eSStefano Zampini   PetscCall(DMConvert(rdm, DMPLEX, &plex));
8966acf3173eSStefano Zampini   PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL));
8967acf3173eSStefano Zampini   PetscCall(DMPlexGetCellType(plex, cStart, &ct));
8968acf3173eSStefano Zampini   PetscCall(DMDestroy(&plex));
89699566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
8970acf3173eSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
8971acf3173eSStefano Zampini   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
8972acf3173eSStefano Zampini   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname));
8973acf3173eSStefano Zampini   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe));
8974acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)fe, ""));
89759566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
89769566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
89779566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
89789566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
8979acf3173eSStefano Zampini   PetscCall(DMCreateLocalVector(rdm, &lval));
8980acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)*val, lname));
8981acf3173eSStefano Zampini   PetscCall(DMGetLocalSection(rdm, &section));
8982acf3173eSStefano Zampini   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
8983acf3173eSStefano Zampini   PetscCall(VecGetArray(lval, &v));
8984acf3173eSStefano Zampini   for (p = pStart; p < pEnd; ++p) {
8985acf3173eSStefano Zampini     PetscInt cval, dof, off;
898618e14f0cSMatthew G. Knepley 
8987acf3173eSStefano Zampini     PetscCall(PetscSectionGetDof(section, p, &dof));
8988acf3173eSStefano Zampini     if (!dof) continue;
8989acf3173eSStefano Zampini     PetscCall(DMLabelGetValue(label, p, &cval));
8990acf3173eSStefano Zampini     PetscCall(PetscSectionGetOffset(section, p, &off));
8991acf3173eSStefano Zampini     for (PetscInt d = 0; d < dof; d++) v[off + d] = cval;
899218e14f0cSMatthew G. Knepley   }
8993acf3173eSStefano Zampini   PetscCall(VecRestoreArray(lval, &v));
8994acf3173eSStefano Zampini   PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val));
8995acf3173eSStefano Zampini   PetscCall(VecDestroy(&lval));
89969566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
89973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
899818e14f0cSMatthew G. Knepley }
899918e14f0cSMatthew G. Knepley 
900018e14f0cSMatthew G. Knepley /*@
9001ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
9002ca8062c8SMatthew G. Knepley 
900369916449SMatthew G. Knepley   Input Parameter:
9004a1cb98faSBarry Smith . dm - The `DMPLEX` object
9005a1cb98faSBarry Smith 
9006a1cb98faSBarry Smith   Level: developer
9007ca8062c8SMatthew G. Knepley 
900895eb5ee5SVaclav Hapla   Notes:
900995eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
901095eb5ee5SVaclav Hapla 
901120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9012ca8062c8SMatthew G. Knepley 
90131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9014ca8062c8SMatthew G. Knepley @*/
9015d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
9016d71ae5a4SJacob Faibussowitsch {
9017ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
9018ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
9019ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
902057beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
902157beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
9022ca8062c8SMatthew G. Knepley 
9023ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9024ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90259566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
90269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
90279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
9028ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
90299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9030ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
90319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
90329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
9033ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
903442e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
903542e66dfaSMatthew G. Knepley       PetscInt  d;
903642e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
90379371c9d4SSatish Balay         if (cone[c] == cone[d]) {
90389371c9d4SSatish Balay           dup = PETSC_TRUE;
90399371c9d4SSatish Balay           break;
90409371c9d4SSatish Balay         }
904142e66dfaSMatthew G. Knepley       }
90429566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
90439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
9044ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
9045ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
9046ca8062c8SMatthew G. Knepley       }
904742e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
904863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
904948a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
90509566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
905163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
905248a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
90539566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
905463a3b9bcSJacob 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]);
9055f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
9056ca8062c8SMatthew G. Knepley       }
905742e66dfaSMatthew G. Knepley     }
90589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
90599371c9d4SSatish Balay     if (p != pp) {
90609371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
90619371c9d4SSatish Balay       continue;
90629371c9d4SSatish Balay     }
90639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
90649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
9065ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
90669566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
90679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
9068ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
90699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
90709371c9d4SSatish Balay         if (cone[c] != pp) {
90719371c9d4SSatish Balay           c = 0;
90729371c9d4SSatish Balay           break;
90739371c9d4SSatish Balay         }
9074ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
9075ca8062c8SMatthew G. Knepley       }
9076ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
907763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
907848a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
90799566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
908063a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
908148a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
90829566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
908363a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
9084ca8062c8SMatthew G. Knepley       }
9085ca8062c8SMatthew G. Knepley     }
9086ca8062c8SMatthew G. Knepley   }
908757beb4faSStefano Zampini   if (storagecheck) {
90889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
90899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
909063a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
909157beb4faSStefano Zampini   }
90923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9093ca8062c8SMatthew G. Knepley }
9094ca8062c8SMatthew G. Knepley 
9095412e9a14SMatthew G. Knepley /*
9096412e9a14SMatthew 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.
9097412e9a14SMatthew G. Knepley */
9098d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
9099d71ae5a4SJacob Faibussowitsch {
9100412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
9101412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
9102412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
9103412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
9104412e9a14SMatthew G. Knepley 
9105412e9a14SMatthew G. Knepley   PetscFunctionBegin;
9106412e9a14SMatthew G. Knepley   *unsplit = 0;
9107412e9a14SMatthew G. Knepley   switch (ct) {
9108d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
9109d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
9110d71ae5a4SJacob Faibussowitsch     break;
9111412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
91129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
91139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9114412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
91159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
9116412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
9117412e9a14SMatthew G. Knepley     }
9118412e9a14SMatthew G. Knepley     break;
9119412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
9120412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
91219566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
91229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9123412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
91249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
91259566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
9126412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
91279566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
9128412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
9129412e9a14SMatthew G. Knepley           PetscInt p;
91309371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
91319371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
9132412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
9133412e9a14SMatthew G. Knepley         }
9134412e9a14SMatthew G. Knepley       }
9135412e9a14SMatthew G. Knepley     }
9136412e9a14SMatthew G. Knepley     break;
9137d71ae5a4SJacob Faibussowitsch   default:
9138d71ae5a4SJacob Faibussowitsch     break;
9139412e9a14SMatthew G. Knepley   }
9140412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
91419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
9142412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
9143412e9a14SMatthew G. Knepley   }
91443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9145412e9a14SMatthew G. Knepley }
9146412e9a14SMatthew G. Knepley 
9147ca8062c8SMatthew G. Knepley /*@
9148ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
9149ca8062c8SMatthew G. Knepley 
9150ca8062c8SMatthew G. Knepley   Input Parameters:
9151a1cb98faSBarry Smith + dm         - The `DMPLEX` object
915258723a97SMatthew G. Knepley - cellHeight - Normally 0
9153ca8062c8SMatthew G. Knepley 
9154a1cb98faSBarry Smith   Level: developer
9155a1cb98faSBarry Smith 
915695eb5ee5SVaclav Hapla   Notes:
915795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
915825c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
9159ca8062c8SMatthew G. Knepley 
916020f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
916195eb5ee5SVaclav Hapla 
91621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9163ca8062c8SMatthew G. Knepley @*/
9164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
9165d71ae5a4SJacob Faibussowitsch {
9166412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
9167412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
9168412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
9169ca8062c8SMatthew G. Knepley 
9170ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9171ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91729566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
91739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
91749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9175412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9176412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
9177412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
917858723a97SMatthew G. Knepley 
91799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
918063a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
9181412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
9182412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
91839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
918463a3b9bcSJacob 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));
9185412e9a14SMatthew G. Knepley     }
91869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
918758723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
918858723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
9189412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
919058723a97SMatthew G. Knepley     }
91919566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
9192412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
9193412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
9194412e9a14SMatthew G. Knepley       PetscInt unsplit;
919542363296SMatthew G. Knepley 
91969566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9197412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
919842363296SMatthew G. Knepley     }
919963a3b9bcSJacob 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));
920042363296SMatthew G. Knepley   }
92013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9202ca8062c8SMatthew G. Knepley }
92039bf0dad6SMatthew G. Knepley 
92049bf0dad6SMatthew G. Knepley /*@
92059bf0dad6SMatthew 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
92069bf0dad6SMatthew G. Knepley 
920720f4b53cSBarry Smith   Collective
9208899ea2b8SJacob Faibussowitsch 
92099bf0dad6SMatthew G. Knepley   Input Parameters:
9210a1cb98faSBarry Smith + dm         - The `DMPLEX` object
92119bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
92129bf0dad6SMatthew G. Knepley 
9213a1cb98faSBarry Smith   Level: developer
9214a1cb98faSBarry Smith 
921545da879fSVaclav Hapla   Notes:
921645da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
921745da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
921845da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
921945da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
92209bf0dad6SMatthew G. Knepley 
9221a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
922295eb5ee5SVaclav Hapla 
92231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
92249bf0dad6SMatthew G. Knepley @*/
9225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
9226d71ae5a4SJacob Faibussowitsch {
9227ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
9228899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
92299bf0dad6SMatthew G. Knepley 
92309bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
92319bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92328f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
92333ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
92348f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
92353ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
92363ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9237899ea2b8SJacob Faibussowitsch   }
9238899ea2b8SJacob Faibussowitsch 
92399566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
92409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
92419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9242ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
92439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
92443554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
9245412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
9246412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
9247ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
9248412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
9249412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
92509bf0dad6SMatthew G. Knepley 
92519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
92529566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9253412e9a14SMatthew G. Knepley       if (unsplit) continue;
92549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
92559566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
92569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
92579566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
92589bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
92599bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
92609bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
92619bf0dad6SMatthew G. Knepley       }
92629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
926363a3b9bcSJacob 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);
92649bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
9265d4961f80SStefano Zampini         DMPolytopeType fct;
92669bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
92679bf0dad6SMatthew G. Knepley 
92689566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
92699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
92709bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
92719bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
92729bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
92739bf0dad6SMatthew G. Knepley         }
927463a3b9bcSJacob 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]);
92759bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
9276b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
9277b5a892a1SMatthew G. Knepley             PetscInt v1;
9278b5a892a1SMatthew G. Knepley 
92799566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
928063a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
92819566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
928263a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
92839566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
928463a3b9bcSJacob 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]);
9285b5a892a1SMatthew G. Knepley           }
92869bf0dad6SMatthew G. Knepley         }
92879566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
9288412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
92899bf0dad6SMatthew G. Knepley       }
92909566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
92919566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
92929bf0dad6SMatthew G. Knepley     }
92933554e41dSMatthew G. Knepley   }
92943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9295552f7358SJed Brown }
92963913d7c8SMatthew G. Knepley 
9297bb6a34a8SMatthew G. Knepley /*@
9298bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
9299bb6a34a8SMatthew G. Knepley 
9300bb6a34a8SMatthew G. Knepley   Input Parameter:
9301a1cb98faSBarry Smith . dm - The `DMPLEX` object
9302a1cb98faSBarry Smith 
9303a1cb98faSBarry Smith   Level: developer
9304bb6a34a8SMatthew G. Knepley 
930595eb5ee5SVaclav Hapla   Notes:
930695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
930795eb5ee5SVaclav Hapla 
930820f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9309bb6a34a8SMatthew G. Knepley 
93101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9311bb6a34a8SMatthew G. Knepley @*/
9312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
9313d71ae5a4SJacob Faibussowitsch {
9314a2a9e04cSMatthew G. Knepley   Vec       coordinates;
9315bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
9316bb6a34a8SMatthew G. Knepley   PetscReal vol;
931751a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
9318bb6a34a8SMatthew G. Knepley 
9319bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
93209566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
93219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
93223ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
93239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
9324bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
93259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
9326a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
93279566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
93283ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
9329412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9330412e9a14SMatthew G. Knepley     DMPolytopeType ct;
9331412e9a14SMatthew G. Knepley     PetscInt       unsplit;
9332412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
9333412e9a14SMatthew G. Knepley 
93349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
9335412e9a14SMatthew G. Knepley     switch (ct) {
9336412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
9337412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9338d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9339d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
9340d71ae5a4SJacob Faibussowitsch       break;
9341d71ae5a4SJacob Faibussowitsch     default:
9342d71ae5a4SJacob Faibussowitsch       break;
9343412e9a14SMatthew G. Knepley     }
9344412e9a14SMatthew G. Knepley     switch (ct) {
9345412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
9346412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9347412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9348d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
9349d71ae5a4SJacob Faibussowitsch       continue;
9350d71ae5a4SJacob Faibussowitsch     default:
9351d71ae5a4SJacob Faibussowitsch       break;
9352412e9a14SMatthew G. Knepley     }
93539566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9354412e9a14SMatthew G. Knepley     if (unsplit) continue;
93559566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
93561dca8a05SBarry 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);
935763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
93586858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
93596858538eSMatthew G. Knepley     if (depth > 1) {
93609566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
93611dca8a05SBarry 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);
936263a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9363bb6a34a8SMatthew G. Knepley     }
9364bb6a34a8SMatthew G. Knepley   }
93653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9366bb6a34a8SMatthew G. Knepley }
9367bb6a34a8SMatthew G. Knepley 
936803da9461SVaclav Hapla /*@
936920f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
93707726db96SVaclav Hapla 
937120f4b53cSBarry Smith   Collective
937203da9461SVaclav Hapla 
937303da9461SVaclav Hapla   Input Parameters:
9374a1cb98faSBarry Smith + dm              - The `DMPLEX` object
937520f4b53cSBarry Smith . pointSF         - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9376a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9377a1cb98faSBarry Smith 
9378a1cb98faSBarry Smith   Level: developer
937903da9461SVaclav Hapla 
9380e83a0d2dSVaclav Hapla   Notes:
9381e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
938203da9461SVaclav Hapla 
9383a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
938495eb5ee5SVaclav Hapla 
9385baca6076SPierre Jolivet   Extra roots can come from periodic cuts, where additional points appear on the boundary
9386d7d32a9aSMatthew G. Knepley 
93871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
938803da9461SVaclav Hapla @*/
9389d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9390d71ae5a4SJacob Faibussowitsch {
93917726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
93927726db96SVaclav Hapla   const PetscInt    *locals;
93937726db96SVaclav Hapla   const PetscSFNode *remotes;
9394f0cfc026SVaclav Hapla   PetscBool          distributed;
93957726db96SVaclav Hapla   MPI_Comm           comm;
93967726db96SVaclav Hapla   PetscMPIInt        rank;
939703da9461SVaclav Hapla 
939803da9461SVaclav Hapla   PetscFunctionBegin;
939903da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94007726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
94017726db96SVaclav Hapla   else pointSF = dm->sf;
94027726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
94037726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
94047726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
94057726db96SVaclav Hapla   {
94067726db96SVaclav Hapla     PetscMPIInt mpiFlag;
94077726db96SVaclav Hapla 
94087726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
94097726db96SVaclav 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);
94107726db96SVaclav Hapla   }
94117726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
94129566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
94137726db96SVaclav Hapla   if (!distributed) {
94147726db96SVaclav 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);
94153ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
94168918e3e2SVaclav Hapla   }
94177726db96SVaclav 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);
94187726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
941903da9461SVaclav Hapla 
94207726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
94217726db96SVaclav Hapla   {
94227726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
94237726db96SVaclav Hapla 
94247726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
94257726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9426d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
94277726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
94287726db96SVaclav Hapla   }
94297726db96SVaclav Hapla 
94307726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
94317726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
94327726db96SVaclav 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);
94337726db96SVaclav Hapla   }
94347726db96SVaclav Hapla 
94357726db96SVaclav Hapla   /* Check there are no cells in interface */
94367726db96SVaclav Hapla   if (!overlap) {
94377726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
94387726db96SVaclav Hapla 
94399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9441f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
94427726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9443f5869d18SMatthew G. Knepley 
94447726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
94457726db96SVaclav Hapla     }
944603da9461SVaclav Hapla   }
9447ece87651SVaclav Hapla 
94487726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
94497726db96SVaclav Hapla   {
94507726db96SVaclav Hapla     const PetscInt *rootdegree;
94517726db96SVaclav Hapla 
94527726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
94537726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9454f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
94557726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9456f5869d18SMatthew G. Knepley       const PetscInt *cone;
9457f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9458f5869d18SMatthew G. Knepley 
94599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
94609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9461f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9462f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
94637726db96SVaclav Hapla           if (locals) {
94649566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
94657726db96SVaclav Hapla           } else {
94667726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
94677726db96SVaclav Hapla           }
946863a3b9bcSJacob 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]);
9469f5869d18SMatthew G. Knepley         }
9470f5869d18SMatthew G. Knepley       }
9471ece87651SVaclav Hapla     }
94727726db96SVaclav Hapla   }
94733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
947403da9461SVaclav Hapla }
947503da9461SVaclav Hapla 
94767f9d8d6cSVaclav Hapla /*@
947720f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
94787f9d8d6cSVaclav Hapla 
94797f9d8d6cSVaclav Hapla   Input Parameter:
9480a1cb98faSBarry Smith . dm - The `DMPLEX` object
9481a1cb98faSBarry Smith 
9482a1cb98faSBarry Smith   Level: developer
94837f9d8d6cSVaclav Hapla 
94847f9d8d6cSVaclav Hapla   Notes:
94857f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
94867f9d8d6cSVaclav Hapla 
948720f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
94887f9d8d6cSVaclav Hapla 
948920f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
94907f9d8d6cSVaclav Hapla 
94911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
94927f9d8d6cSVaclav Hapla @*/
9493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9494d71ae5a4SJacob Faibussowitsch {
94957f9d8d6cSVaclav Hapla   PetscInt cellHeight;
94967f9d8d6cSVaclav Hapla 
9497b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94987f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94999566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
95009566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
95019566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
95029566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9503d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
95049566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
95053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9506b5a892a1SMatthew G. Knepley }
9507b5a892a1SMatthew G. Knepley 
95089371c9d4SSatish Balay typedef struct cell_stats {
9509068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9510068a5610SStefano Zampini   PetscInt  count;
9511068a5610SStefano Zampini } cell_stats_t;
9512068a5610SStefano Zampini 
9513d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9514d71ae5a4SJacob Faibussowitsch {
9515068a5610SStefano Zampini   PetscInt i, N = *len;
9516068a5610SStefano Zampini 
9517068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9518068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9519068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9520068a5610SStefano Zampini 
9521068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9522068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9523068a5610SStefano Zampini     B->sum += A->sum;
9524068a5610SStefano Zampini     B->squaresum += A->squaresum;
9525068a5610SStefano Zampini     B->count += A->count;
9526068a5610SStefano Zampini   }
9527068a5610SStefano Zampini }
9528068a5610SStefano Zampini 
9529068a5610SStefano Zampini /*@
953043fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9531068a5610SStefano Zampini 
953220f4b53cSBarry Smith   Collective
95338261a58bSMatthew G. Knepley 
9534068a5610SStefano Zampini   Input Parameters:
9535a1cb98faSBarry Smith + dm        - The `DMPLEX` object
953620f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9537a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9538a1cb98faSBarry Smith 
9539a1cb98faSBarry Smith   Level: developer
9540068a5610SStefano Zampini 
954195eb5ee5SVaclav Hapla   Notes:
954295eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
954395eb5ee5SVaclav Hapla 
9544a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9545068a5610SStefano Zampini 
95461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9547068a5610SStefano Zampini @*/
9548d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9549d71ae5a4SJacob Faibussowitsch {
9550068a5610SStefano Zampini   DM           dmCoarse;
955143fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
955243fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
955343fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
955443fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9555412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
955643fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9557068a5610SStefano Zampini 
9558068a5610SStefano Zampini   PetscFunctionBegin;
9559068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9560068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9561068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9562068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9563068a5610SStefano Zampini   stats.count                 = 0;
9564068a5610SStefano Zampini 
95659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
95669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
95679566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
95689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
95699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
95709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9571412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9572068a5610SStefano Zampini     PetscInt  i;
9573068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9574068a5610SStefano Zampini 
95759566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
957663a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
957743fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9578068a5610SStefano Zampini       frobJ += J[i] * J[i];
9579068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9580068a5610SStefano Zampini     }
9581068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9582068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9583068a5610SStefano Zampini 
9584068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9585068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9586068a5610SStefano Zampini     stats.sum += cond;
9587068a5610SStefano Zampini     stats.squaresum += cond2;
9588068a5610SStefano Zampini     stats.count++;
95898261a58bSMatthew G. Knepley     if (output && cond > limit) {
959043fa8764SMatthew G. Knepley       PetscSection coordSection;
959143fa8764SMatthew G. Knepley       Vec          coordsLocal;
959243fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
959343fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
959443fa8764SMatthew G. Knepley 
95959566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
95969566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
95979566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
959863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
959943fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
960063a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
960143fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
96029566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
96039566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
960443fa8764SMatthew G. Knepley         }
96059566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
960643fa8764SMatthew G. Knepley       }
96079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
960843fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
960943fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
961043fa8764SMatthew G. Knepley 
961143fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
961243fa8764SMatthew G. Knepley           PetscReal len;
961343fa8764SMatthew G. Knepley 
96149566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
961563a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
961643fa8764SMatthew G. Knepley         }
961743fa8764SMatthew G. Knepley       }
96189566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
96199566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
962043fa8764SMatthew G. Knepley     }
9621068a5610SStefano Zampini   }
96229566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9623068a5610SStefano Zampini 
9624068a5610SStefano Zampini   if (size > 1) {
9625068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9626068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9627068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9628068a5610SStefano Zampini     MPI_Op       statReduce;
9629068a5610SStefano Zampini 
96309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
96319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
96329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
96339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
96349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
96359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9636068a5610SStefano Zampini   } else {
96379566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9638068a5610SStefano Zampini   }
9639dd400576SPatrick Sanan   if (rank == 0) {
9640068a5610SStefano Zampini     count = globalStats.count;
9641068a5610SStefano Zampini     min   = globalStats.min;
9642068a5610SStefano Zampini     max   = globalStats.max;
9643068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9644068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9645068a5610SStefano Zampini   }
9646068a5610SStefano Zampini 
964748a46eb9SPierre 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));
96489566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9649068a5610SStefano Zampini 
96509566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9651068a5610SStefano Zampini   if (dmCoarse) {
9652068a5610SStefano Zampini     PetscBool isplex;
9653068a5610SStefano Zampini 
96549566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
96551baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9656068a5610SStefano Zampini   }
96573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9658068a5610SStefano Zampini }
9659068a5610SStefano Zampini 
9660f108dbd7SJacob Faibussowitsch /*@
9661f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9662f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9663f108dbd7SJacob Faibussowitsch 
966420f4b53cSBarry Smith   Collective
9665f108dbd7SJacob Faibussowitsch 
9666f108dbd7SJacob Faibussowitsch   Input Parameters:
9667a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9668a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9669f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9670f108dbd7SJacob Faibussowitsch 
9671f108dbd7SJacob Faibussowitsch   Output Parameters:
967220f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9673a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9674f108dbd7SJacob Faibussowitsch 
9675f108dbd7SJacob Faibussowitsch   Options Database Keys:
9676a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9677f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view   - view OrthQual vector.
9678f108dbd7SJacob Faibussowitsch 
9679a1cb98faSBarry Smith   Level: intermediate
9680a1cb98faSBarry Smith 
9681f108dbd7SJacob Faibussowitsch   Notes:
9682a4e35b19SJacob Faibussowitsch   Orthogonal quality is given by the following formula\:
9683f108dbd7SJacob Faibussowitsch 
9684a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9685f108dbd7SJacob Faibussowitsch 
9686f108dbd7SJacob 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
9687f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9688f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9689f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9690f108dbd7SJacob Faibussowitsch 
9691f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9692f108dbd7SJacob Faibussowitsch 
9693a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9694f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9695f108dbd7SJacob Faibussowitsch 
9696f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9697f108dbd7SJacob Faibussowitsch 
96981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9699f108dbd7SJacob Faibussowitsch @*/
9700d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9701d71ae5a4SJacob Faibussowitsch {
97026ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
97036ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
97046ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9705f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
97066ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9707f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9708f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9709f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9710f108dbd7SJacob Faibussowitsch   IS                     glob;
9711f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9712f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9713f108dbd7SJacob Faibussowitsch 
9714f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9715f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9716ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
97174f572ea9SToby Isaac   PetscAssertPointer(OrthQual, 4);
97186bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
97199566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
97209566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
972163a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
97226ed19f2fSJacob Faibussowitsch   {
97236ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
97246ed19f2fSJacob Faibussowitsch 
97259566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9726f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9727f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9728f108dbd7SJacob Faibussowitsch 
97299566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
973098921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9731f108dbd7SJacob Faibussowitsch     }
97326ed19f2fSJacob Faibussowitsch   }
9733f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
97344f572ea9SToby Isaac     PetscAssertPointer(OrthQualLabel, 5);
97359566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
97369566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
97379371c9d4SSatish Balay   } else {
97389371c9d4SSatish Balay     *OrthQualLabel = NULL;
97399371c9d4SSatish Balay   }
97409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
97419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
97429566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
97439566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
97449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
97459566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
97469566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
97479566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
97489566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
97499566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
97509566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
97519566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
97529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
97539566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
97549566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
97559566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
97569566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
97579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
97586ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
97596ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9760f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9761f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9762898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9763f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9764f108dbd7SJacob Faibussowitsch 
97656ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9766f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9767f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
97689566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
97699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9770f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
97719566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
97726ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
97736ed19f2fSJacob Faibussowitsch       PetscInt         i;
97746ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9775f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9776f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9777f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9778f108dbd7SJacob Faibussowitsch 
9779f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9780f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
97819566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9782f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
97836ed19f2fSJacob Faibussowitsch       {
97846ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
97856ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
97866ed19f2fSJacob Faibussowitsch 
97879566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
97889566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
97899566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
97906ed19f2fSJacob Faibussowitsch       }
9791f108dbd7SJacob Faibussowitsch 
9792f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9793f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9794f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9795f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9796f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9797addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9798addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9799addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9800f108dbd7SJacob Faibussowitsch       }
9801addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9802addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9803addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9804f108dbd7SJacob Faibussowitsch 
9805f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9806f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9807f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9808f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9809f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9810f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9811f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9812f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9813f108dbd7SJacob Faibussowitsch       }
9814ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9815ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9816f108dbd7SJacob Faibussowitsch     }
98179566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
98189566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9819f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
98206ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9821f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
98229566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9823f108dbd7SJacob Faibussowitsch     }
9824f108dbd7SJacob Faibussowitsch   }
98259566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
98269566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
98279566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
98289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
98299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
98309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9831f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
98329566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9833f108dbd7SJacob Faibussowitsch   }
98349566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
9835cd791dc2SBarry Smith   PetscCall(PetscOptionsRestoreViewer(&vwr));
98369566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
98373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9838f108dbd7SJacob Faibussowitsch }
9839f108dbd7SJacob Faibussowitsch 
9840d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
98411eb70e55SToby Isaac  * interpolator construction */
9842d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9843d71ae5a4SJacob Faibussowitsch {
98441eb70e55SToby Isaac   PetscSection section, newSection, gsection;
98451eb70e55SToby Isaac   PetscSF      sf;
98461eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
98471eb70e55SToby Isaac 
98481eb70e55SToby Isaac   PetscFunctionBegin;
98491eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98504f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
98519566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
98529566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9853712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
98541eb70e55SToby Isaac   if (!ghasConstraints) {
98559566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
98561eb70e55SToby Isaac     *odm = dm;
98573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
98581eb70e55SToby Isaac   }
98599566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
98609566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
98619566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
98629566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
9863eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection));
98649566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
98659566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
98663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98671eb70e55SToby Isaac }
98681eb70e55SToby Isaac 
9869d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9870d71ae5a4SJacob Faibussowitsch {
98711eb70e55SToby Isaac   DM        dmco, dmfo;
98721eb70e55SToby Isaac   Mat       interpo;
98731eb70e55SToby Isaac   Vec       rscale;
98741eb70e55SToby Isaac   Vec       cglobalo, clocal;
98751eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
98761eb70e55SToby Isaac   PetscBool regular;
98771eb70e55SToby Isaac 
98781eb70e55SToby Isaac   PetscFunctionBegin;
98799566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
98809566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
98819566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
98829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
98839566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
98849566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
98859566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
98869566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
98879566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
98889566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
98899566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
98909566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
98919566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
98929566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
98939566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
98949566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
98959566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
98969566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
98979566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
98989566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
98999566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
99009566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
99019566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
99029566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
99031eb70e55SToby Isaac   *shift = fglobal;
99049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
99059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
99069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
99079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
99089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
99099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
99109566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
99119566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
99123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99131eb70e55SToby Isaac }
99141eb70e55SToby Isaac 
9915d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9916d71ae5a4SJacob Faibussowitsch {
99171eb70e55SToby Isaac   PetscObject shifto;
99181eb70e55SToby Isaac   Vec         shift;
99191eb70e55SToby Isaac 
99201eb70e55SToby Isaac   PetscFunctionBegin;
99211eb70e55SToby Isaac   if (!interp) {
99221eb70e55SToby Isaac     Vec rscale;
99231eb70e55SToby Isaac 
99249566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
99259566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
99261eb70e55SToby Isaac   } else {
99279566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
99281eb70e55SToby Isaac   }
99299566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
99301eb70e55SToby Isaac   if (!shifto) {
99319566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
99329566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
99331eb70e55SToby Isaac     shifto = (PetscObject)shift;
99349566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
99351eb70e55SToby Isaac   }
99361eb70e55SToby Isaac   shift = (Vec)shifto;
99379566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
99389566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
99399566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
99403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99411eb70e55SToby Isaac }
99421eb70e55SToby Isaac 
9943bceba477SMatthew G. Knepley /* Pointwise interpolation
9944bceba477SMatthew G. Knepley      Just code FEM for now
9945bceba477SMatthew G. Knepley      u^f = I u^c
99464ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
99474ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
99484ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9949bceba477SMatthew G. Knepley */
9950d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9951d71ae5a4SJacob Faibussowitsch {
9952bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9953bceba477SMatthew G. Knepley   PetscInt     m, n;
9954a063dac3SMatthew G. Knepley   void        *ctx;
995568132eb9SMatthew G. Knepley   DM           cdm;
9956cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9957bceba477SMatthew G. Knepley 
9958bceba477SMatthew G. Knepley   PetscFunctionBegin;
99599566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
99609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
99619566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
99629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
996368132eb9SMatthew G. Knepley 
99649566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
99659566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
99669566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
99679566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
99689566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
996968132eb9SMatthew G. Knepley 
99709566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
99719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
99729566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
99739566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
99749566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
99754db47ee9SStefano Zampini   if (scaling) {
99765d1c2e58SMatthew G. Knepley     /* Use naive scaling */
99779566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
99784db47ee9SStefano Zampini   }
99793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9980a063dac3SMatthew G. Knepley }
9981bceba477SMatthew G. Knepley 
9982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9983d71ae5a4SJacob Faibussowitsch {
99846dbf9973SLawrence Mitchell   VecScatter ctx;
998590748bafSMatthew G. Knepley 
9986a063dac3SMatthew G. Knepley   PetscFunctionBegin;
99879566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
99889566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
99899566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
99903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9991bceba477SMatthew G. Knepley }
9992bceba477SMatthew G. Knepley 
9993d71ae5a4SJacob 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[])
9994d71ae5a4SJacob Faibussowitsch {
999500635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
999600635df3SMatthew G. Knepley   PetscInt       c;
999700635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
99983e9753d6SMatthew G. Knepley }
99993e9753d6SMatthew G. Knepley 
10000d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
10001d71ae5a4SJacob Faibussowitsch {
10002b4937a87SMatthew G. Knepley   DM           dmc;
10003b4937a87SMatthew G. Knepley   PetscDS      ds;
10004b4937a87SMatthew G. Knepley   Vec          ones, locmass;
10005b4937a87SMatthew G. Knepley   IS           cellIS;
10006b4937a87SMatthew G. Knepley   PetscFormKey key;
10007b4937a87SMatthew G. Knepley   PetscInt     depth;
10008b4937a87SMatthew G. Knepley 
10009b4937a87SMatthew G. Knepley   PetscFunctionBegin;
100109566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
100119566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
100129566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
100139566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
100149566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
100159566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
100169566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
100179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
100189566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
100199566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
100209566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
10021b4937a87SMatthew G. Knepley   key.label = NULL;
10022b4937a87SMatthew G. Knepley   key.value = 0;
10023b4937a87SMatthew G. Knepley   key.field = 0;
10024b4937a87SMatthew G. Knepley   key.part  = 0;
100259566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
100269566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
100279566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
100289566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
100299566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
100309566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
100319566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
100329566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
100333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10034b4937a87SMatthew G. Knepley }
10035b4937a87SMatthew G. Knepley 
10036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
10037d71ae5a4SJacob Faibussowitsch {
10038bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
10039bd041c0cSMatthew G. Knepley   PetscInt     m, n;
10040bd041c0cSMatthew G. Knepley   void        *ctx;
10041bd041c0cSMatthew G. Knepley   DM           cdm;
10042bd041c0cSMatthew G. Knepley   PetscBool    regular;
10043bd041c0cSMatthew G. Knepley 
10044bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
100453e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
100463e9753d6SMatthew G. Knepley     DM            dmc;
100473e9753d6SMatthew G. Knepley     PetscDS       ds;
10048b4937a87SMatthew G. Knepley     PetscWeakForm wf;
100493e9753d6SMatthew G. Knepley     Vec           u;
100503e9753d6SMatthew G. Knepley     IS            cellIS;
1005106ad1575SMatthew G. Knepley     PetscFormKey  key;
100523e9753d6SMatthew G. Knepley     PetscInt      depth;
100533e9753d6SMatthew G. Knepley 
100549566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
100559566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
100569566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
100579566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
100589566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
100599566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
100609566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
100618d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
100629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
100639566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
100649566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
100656528b96dSMatthew G. Knepley     key.label = NULL;
100666528b96dSMatthew G. Knepley     key.value = 0;
100676528b96dSMatthew G. Knepley     key.field = 0;
1006806ad1575SMatthew G. Knepley     key.part  = 0;
100699566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
100709566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
100718d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
100729566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
100733e9753d6SMatthew G. Knepley   } else {
100749566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
100759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
100769566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
100779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
10078bd041c0cSMatthew G. Knepley 
100799566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
100809566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
100819566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
100829566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
10083bd041c0cSMatthew G. Knepley 
100849566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
100859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
100869566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
100879566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
100883e9753d6SMatthew G. Knepley   }
100899566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
100903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10091bd041c0cSMatthew G. Knepley }
10092bd041c0cSMatthew G. Knepley 
100930aef6b92SMatthew G. Knepley /*@
100940aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
100950aef6b92SMatthew G. Knepley 
100960aef6b92SMatthew G. Knepley   Input Parameter:
10097a1cb98faSBarry Smith . dm - The `DMPLEX` object
100980aef6b92SMatthew G. Knepley 
100990aef6b92SMatthew G. Knepley   Output Parameter:
101000aef6b92SMatthew G. Knepley . regular - The flag
101010aef6b92SMatthew G. Knepley 
101020aef6b92SMatthew G. Knepley   Level: intermediate
101030aef6b92SMatthew G. Knepley 
101041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
101050aef6b92SMatthew G. Knepley @*/
10106d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
10107d71ae5a4SJacob Faibussowitsch {
101080aef6b92SMatthew G. Knepley   PetscFunctionBegin;
101090aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101104f572ea9SToby Isaac   PetscAssertPointer(regular, 2);
101110aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
101123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101130aef6b92SMatthew G. Knepley }
101140aef6b92SMatthew G. Knepley 
101150aef6b92SMatthew G. Knepley /*@
101160aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
101170aef6b92SMatthew G. Knepley 
101180aef6b92SMatthew G. Knepley   Input Parameters:
10119a1cb98faSBarry Smith + dm      - The `DMPLEX` object
101200aef6b92SMatthew G. Knepley - regular - The flag
101210aef6b92SMatthew G. Knepley 
101220aef6b92SMatthew G. Knepley   Level: intermediate
101230aef6b92SMatthew G. Knepley 
101241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
101250aef6b92SMatthew G. Knepley @*/
10126d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
10127d71ae5a4SJacob Faibussowitsch {
101280aef6b92SMatthew G. Knepley   PetscFunctionBegin;
101290aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101300aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
101313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101320aef6b92SMatthew G. Knepley }
101330aef6b92SMatthew G. Knepley 
10134a68b90caSToby Isaac /*@
10135f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
10136a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
10137a68b90caSToby Isaac 
10138a1cb98faSBarry Smith   Not Collective
10139a68b90caSToby Isaac 
10140f899ff85SJose E. Roman   Input Parameter:
10141a1cb98faSBarry Smith . dm - The `DMPLEX` object
10142a68b90caSToby Isaac 
10143a68b90caSToby Isaac   Output Parameters:
1014420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
1014520f4b53cSBarry Smith - anchorIS      - If not `NULL`, set to the list of anchors indexed by `anchorSection`
10146a68b90caSToby Isaac 
10147a68b90caSToby Isaac   Level: intermediate
10148a68b90caSToby Isaac 
101491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
10150a68b90caSToby Isaac @*/
10151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
10152d71ae5a4SJacob Faibussowitsch {
10153a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
10154a68b90caSToby Isaac 
10155a68b90caSToby Isaac   PetscFunctionBegin;
10156a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101579566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
10158a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
10159a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
101603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10161a68b90caSToby Isaac }
10162a68b90caSToby Isaac 
10163a68b90caSToby Isaac /*@
10164a4e35b19SJacob Faibussowitsch   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.
10165a68b90caSToby Isaac 
1016620f4b53cSBarry Smith   Collective
10167a68b90caSToby Isaac 
10168a68b90caSToby Isaac   Input Parameters:
10169a1cb98faSBarry Smith + dm            - The `DMPLEX` object
10170a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
10171a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10172a1cb98faSBarry Smith - anchorIS      - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10173a68b90caSToby Isaac 
10174a68b90caSToby Isaac   Level: intermediate
10175a68b90caSToby Isaac 
10176a1cb98faSBarry Smith   Notes:
10177a4e35b19SJacob Faibussowitsch   Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to
10178a4e35b19SJacob Faibussowitsch   an outside value, the anchor constraints set a point's degrees of freedom to be a linear
10179a4e35b19SJacob Faibussowitsch   combination of other points' degrees of freedom.
10180a4e35b19SJacob Faibussowitsch 
10181a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
10182a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
10183a1cb98faSBarry Smith 
1018420f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
10185a1cb98faSBarry Smith 
101861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
10187a68b90caSToby Isaac @*/
10188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
10189d71ae5a4SJacob Faibussowitsch {
10190a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
10191e228b242SToby Isaac   PetscMPIInt result;
10192a68b90caSToby Isaac 
10193a68b90caSToby Isaac   PetscFunctionBegin;
10194a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10195e228b242SToby Isaac   if (anchorSection) {
10196e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
101979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
101981dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
10199e228b242SToby Isaac   }
10200e228b242SToby Isaac   if (anchorIS) {
10201e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
102029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
102031dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
10204e228b242SToby Isaac   }
10205a68b90caSToby Isaac 
102069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
102079566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
10208a68b90caSToby Isaac   plex->anchorSection = anchorSection;
10209a68b90caSToby Isaac 
102109566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
102119566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
10212a68b90caSToby Isaac   plex->anchorIS = anchorIS;
10213a68b90caSToby Isaac 
10214cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
10215a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
10216a68b90caSToby Isaac     const PetscInt *anchors;
10217a68b90caSToby Isaac 
102189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
102199566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
102209566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
10221a68b90caSToby Isaac     for (a = 0; a < size; a++) {
10222a68b90caSToby Isaac       PetscInt p;
10223a68b90caSToby Isaac 
10224a68b90caSToby Isaac       p = anchors[a];
10225a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
10226a68b90caSToby Isaac         PetscInt dof;
10227a68b90caSToby Isaac 
102289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10229a68b90caSToby Isaac         if (dof) {
102309566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
1023163a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
10232a68b90caSToby Isaac         }
10233a68b90caSToby Isaac       }
10234a68b90caSToby Isaac     }
102359566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
10236a68b90caSToby Isaac   }
10237f7c74593SToby Isaac   /* reset the generic constraints */
102389566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
102393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10240a68b90caSToby Isaac }
10241a68b90caSToby Isaac 
10242d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
10243d71ae5a4SJacob Faibussowitsch {
10244f7c74593SToby Isaac   PetscSection anchorSection;
102456995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
10246a68b90caSToby Isaac 
10247a68b90caSToby Isaac   PetscFunctionBegin;
10248a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
102509566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
102519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
102526995de1eSToby Isaac   if (numFields) {
10253719ab38cSToby Isaac     PetscInt f;
102549566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
10255719ab38cSToby Isaac 
10256719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
10257719ab38cSToby Isaac       PetscInt numComp;
10258719ab38cSToby Isaac 
102599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
102609566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
10261719ab38cSToby Isaac     }
102626995de1eSToby Isaac   }
102639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
102649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
102656995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
102666995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
102676995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
102689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
10269a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
102709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10271a68b90caSToby Isaac     if (dof) {
102729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
102739566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
10274a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
102759566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
102769566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
10277a68b90caSToby Isaac       }
10278a68b90caSToby Isaac     }
10279a68b90caSToby Isaac   }
102809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
102819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
102823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10283a68b90caSToby Isaac }
10284a68b90caSToby Isaac 
10285d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
10286d71ae5a4SJacob Faibussowitsch {
10287f7c74593SToby Isaac   PetscSection    aSec;
10288ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
102890ac89760SToby Isaac   const PetscInt *anchors;
102900ac89760SToby Isaac   PetscInt        numFields, f;
1029166ad2231SToby Isaac   IS              aIS;
10292e19f7ee6SMark Adams   MatType         mtype;
10293e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
102940ac89760SToby Isaac 
102950ac89760SToby Isaac   PetscFunctionBegin;
102960ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
102989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
102999566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
103009566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
103019566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
103029566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
103039566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
103049566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
10305e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
10306e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
10307e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
103089566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
103099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
103109566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
103116995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
103129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
103139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
103149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
103150ac89760SToby Isaac   i[0] = 0;
103169566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
103170ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
10318f19733c5SToby Isaac     PetscInt rDof, rOff, r;
10319f19733c5SToby Isaac 
103209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
10321f19733c5SToby Isaac     if (!rDof) continue;
103229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103230ac89760SToby Isaac     if (numFields) {
103240ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
103250ac89760SToby Isaac         annz = 0;
10326f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
10327f19733c5SToby Isaac           a = anchors[rOff + r];
10328ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
103299566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
103300ac89760SToby Isaac           annz += aDof;
103310ac89760SToby Isaac         }
103329566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
103339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
10334ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
103350ac89760SToby Isaac       }
103362f7452b8SBarry Smith     } else {
103370ac89760SToby Isaac       annz = 0;
103389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103390ac89760SToby Isaac       for (q = 0; q < dof; q++) {
10340ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
10341ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
103429566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
103430ac89760SToby Isaac         annz += aDof;
103440ac89760SToby Isaac       }
103459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
10347ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
103480ac89760SToby Isaac     }
103490ac89760SToby Isaac   }
103500ac89760SToby Isaac   nnz = i[m];
103519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
103520ac89760SToby Isaac   offset = 0;
103530ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
103540ac89760SToby Isaac     if (numFields) {
103550ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
103569566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
103570ac89760SToby Isaac         for (q = 0; q < dof; q++) {
103580ac89760SToby Isaac           PetscInt rDof, rOff, r;
103599566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
103609566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103610ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
103620ac89760SToby Isaac             PetscInt s;
103630ac89760SToby Isaac 
103640ac89760SToby Isaac             a = anchors[rOff + r];
10365ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
103669566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
103679566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10368ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
103690ac89760SToby Isaac           }
103700ac89760SToby Isaac         }
103710ac89760SToby Isaac       }
103722f7452b8SBarry Smith     } else {
103739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103740ac89760SToby Isaac       for (q = 0; q < dof; q++) {
103750ac89760SToby Isaac         PetscInt rDof, rOff, r;
103769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
103779566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103780ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
103790ac89760SToby Isaac           PetscInt s;
103800ac89760SToby Isaac 
103810ac89760SToby Isaac           a = anchors[rOff + r];
10382ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
103839566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
103849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10385ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
103860ac89760SToby Isaac         }
103870ac89760SToby Isaac       }
103880ac89760SToby Isaac     }
103890ac89760SToby Isaac   }
103909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
103919566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
103929566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
103939566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
103943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103950ac89760SToby Isaac }
103960ac89760SToby Isaac 
10397d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10398d71ae5a4SJacob Faibussowitsch {
10399f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10400f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1040166ad2231SToby Isaac   Mat          cMat;
1040266ad2231SToby Isaac 
1040366ad2231SToby Isaac   PetscFunctionBegin;
1040466ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
104059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1040666ad2231SToby Isaac   if (anchorSection) {
1040744a7f3ddSMatthew G. Knepley     PetscInt Nf;
10408e228b242SToby Isaac 
104099566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
104109566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
104119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
104129566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
104139566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
104149566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
104159566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
104169566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1041766ad2231SToby Isaac   }
104183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1041966ad2231SToby Isaac }
10420a93c429eSMatthew G. Knepley 
10421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10422d71ae5a4SJacob Faibussowitsch {
10423a93c429eSMatthew G. Knepley   IS           subis;
10424a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10425a93c429eSMatthew G. Knepley 
10426a93c429eSMatthew G. Knepley   PetscFunctionBegin;
104279566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1042828b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1042928b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10430a93c429eSMatthew G. Knepley   /* Create subdomain */
10431*30cbcd5dSksagiyam   PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, NULL, subdm));
10432a93c429eSMatthew G. Knepley   /* Create submodel */
104339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
104349566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
104359566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
104369566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
104379566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10438a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10439a93c429eSMatthew G. Knepley   if (is) {
10440a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10441a93c429eSMatthew G. Knepley     IS              spIS;
10442a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10443a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10444a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10445a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10446a93c429eSMatthew G. Knepley 
104479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
104489566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
104499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
104509566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
104519566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
104529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10453a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10454a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10455a93c429eSMatthew G. Knepley 
104569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10457a93c429eSMatthew G. Knepley       if (gdof > 0) {
10458a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10459a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10460a93c429eSMatthew G. Knepley 
104619566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
104629566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10463a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10464a93c429eSMatthew G. Knepley         }
10465a93c429eSMatthew G. Knepley         subSize += pSubSize;
10466a93c429eSMatthew G. Knepley         if (pSubSize) {
10467a93c429eSMatthew G. Knepley           if (bs < 0) {
10468a93c429eSMatthew G. Knepley             bs = pSubSize;
10469a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10470a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10471a93c429eSMatthew G. Knepley             bs = 1;
10472a93c429eSMatthew G. Knepley           }
10473a93c429eSMatthew G. Knepley         }
10474a93c429eSMatthew G. Knepley       }
10475a93c429eSMatthew G. Knepley     }
10476a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
104779371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
104789371c9d4SSatish Balay     bsLocal[1] = bs;
104799566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
104809371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
104819371c9d4SSatish Balay       bs = 1;
104829371c9d4SSatish Balay     } else {
104839371c9d4SSatish Balay       bs = bsMinMax[0];
104849371c9d4SSatish Balay     }
104859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10486a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10487a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10488a93c429eSMatthew G. Knepley 
104899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10490a93c429eSMatthew G. Knepley       if (gdof > 0) {
10491a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10492a93c429eSMatthew G. Knepley 
104939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10494a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10495a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10496a93c429eSMatthew G. Knepley 
10497a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10498a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
104999566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
105009566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10501a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10502a93c429eSMatthew G. Knepley           }
105039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
105049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10505ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10506a93c429eSMatthew G. Knepley         }
10507a93c429eSMatthew G. Knepley       }
10508a93c429eSMatthew G. Knepley     }
105099566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
105109566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10511a93c429eSMatthew G. Knepley     if (bs > 1) {
10512a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10513a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10514a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10515a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
105169371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
105179371c9d4SSatish Balay             set = 0;
105189371c9d4SSatish Balay             break;
105199371c9d4SSatish Balay           }
10520a93c429eSMatthew G. Knepley         }
10521a93c429eSMatthew G. Knepley       }
105229566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10523a93c429eSMatthew G. Knepley     }
10524a93c429eSMatthew G. Knepley     /* Attach nullspace */
10525a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10526a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10527a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10528a93c429eSMatthew G. Knepley     }
10529a93c429eSMatthew G. Knepley     if (f < Nf) {
10530a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
105319566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
105326823f3c5SBlaise Bourdin 
105339566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
105349566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10535a93c429eSMatthew G. Knepley     }
10536a93c429eSMatthew G. Knepley   }
105373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10538a93c429eSMatthew G. Knepley }
10539c0f0dcc3SMatthew G. Knepley 
10540c0f0dcc3SMatthew G. Knepley /*@
10541c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10542c0f0dcc3SMatthew G. Knepley 
10543a1cb98faSBarry Smith   Input Parameters:
10544a1cb98faSBarry Smith + dm    - The `DM`
10545a1cb98faSBarry Smith - dummy - unused argument
10546a1cb98faSBarry Smith 
10547a1cb98faSBarry Smith   Options Database Key:
10548a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10549c0f0dcc3SMatthew G. Knepley 
10550c0f0dcc3SMatthew G. Knepley   Level: developer
10551c0f0dcc3SMatthew G. Knepley 
105521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10553c0f0dcc3SMatthew G. Knepley @*/
10554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10555d71ae5a4SJacob Faibussowitsch {
10556b665b14eSToby Isaac   PetscLogHandler default_handler;
10557b665b14eSToby Isaac 
105582611ad71SToby Isaac   PetscFunctionBegin;
105592611ad71SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10560b665b14eSToby Isaac   PetscCall(PetscLogGetDefaultHandler(&default_handler));
10561b665b14eSToby Isaac   if (default_handler) {
10562c0f0dcc3SMatthew G. Knepley     PetscLogEvent      event;
10563c0f0dcc3SMatthew G. Knepley     PetscEventPerfInfo eventInfo;
10564c0f0dcc3SMatthew G. Knepley     PetscReal          cellRate, flopRate;
10565c0f0dcc3SMatthew G. Knepley     PetscInt           cStart, cEnd, Nf, N;
10566c0f0dcc3SMatthew G. Knepley     const char        *name;
10567c0f0dcc3SMatthew G. Knepley 
105689566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
105699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
105709566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
105719566063dSJacob Faibussowitsch     PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
10572b665b14eSToby Isaac     PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo));
10573c0f0dcc3SMatthew G. Knepley     N        = (cEnd - cStart) * Nf * eventInfo.count;
10574c0f0dcc3SMatthew G. Knepley     flopRate = eventInfo.flops / eventInfo.time;
10575c0f0dcc3SMatthew G. Knepley     cellRate = N / eventInfo.time;
1057663a3b9bcSJacob 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)));
105772611ad71SToby Isaac   } else {
10578b665b14eSToby 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.");
105792611ad71SToby Isaac   }
105803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10581c0f0dcc3SMatthew G. Knepley }
10582