xref: /petsc/src/dm/impls/plex/plex.c (revision 32b276375810fb827f9daaeb19591df524310135)
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>
11c789d87fSToby Isaac #include <petscblaslapack.h>
12552f7358SJed Brown 
13552f7358SJed Brown /* Logging support */
1402f7d72cSksagiyam 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;
15172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate;
16552f7358SJed Brown 
17f39ec787SMatthew G. Knepley PetscBool  Plexcite       = PETSC_FALSE;
18f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n"
19f39ec787SMatthew G. Knepley                             "title     = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n"
20f39ec787SMatthew G. Knepley                             "author    = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n"
21f39ec787SMatthew G. Knepley                             "journal   = {SIAM Journal on Scientific Computing},\n"
22f39ec787SMatthew G. Knepley                             "volume    = {38},\n"
23f39ec787SMatthew G. Knepley                             "number    = {5},\n"
24f39ec787SMatthew G. Knepley                             "pages     = {S143--S155},\n"
25f39ec787SMatthew G. Knepley                             "eprint    = {http://arxiv.org/abs/1506.07749},\n"
26f39ec787SMatthew G. Knepley                             "doi       = {10.1137/15M1026092},\n"
27f39ec787SMatthew G. Knepley                             "year      = {2016},\n"
28f39ec787SMatthew G. Knepley                             "petsc_uses={DMPlex},\n}\n";
29f39ec787SMatthew G. Knepley 
305a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
31552f7358SJed Brown 
32e5337592SStefano Zampini /*@
339318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
349318fe57SMatthew G. Knepley 
359318fe57SMatthew G. Knepley   Input Parameter:
36a1cb98faSBarry Smith . dm - The `DMPLEX` object
379318fe57SMatthew G. Knepley 
389318fe57SMatthew G. Knepley   Output Parameter:
399318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
409318fe57SMatthew G. Knepley 
419318fe57SMatthew G. Knepley   Level: intermediate
429318fe57SMatthew G. Knepley 
43a1cb98faSBarry Smith   Note:
44a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
45a1cb98faSBarry Smith   If the mesh has no cells, this returns `PETSC_FALSE`.
46a1cb98faSBarry Smith 
471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
489318fe57SMatthew G. Knepley @*/
49d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
50d71ae5a4SJacob Faibussowitsch {
519318fe57SMatthew G. Knepley   DMPolytopeType ct;
529318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
539318fe57SMatthew G. Knepley 
549318fe57SMatthew G. Knepley   PetscFunctionBegin;
559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
569371c9d4SSatish Balay   if (cEnd <= cStart) {
579371c9d4SSatish Balay     *simplex = PETSC_FALSE;
583ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
599371c9d4SSatish Balay   }
609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
619318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
639318fe57SMatthew G. Knepley }
649318fe57SMatthew G. Knepley 
659318fe57SMatthew G. Knepley /*@
66412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
67e5337592SStefano Zampini 
68d8d19677SJose E. Roman   Input Parameters:
69a1cb98faSBarry Smith + dm     - The `DMPLEX` object
70412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
71e5337592SStefano Zampini 
72e5337592SStefano Zampini   Output Parameters:
73412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
7440196513SBarry Smith - cEnd   - The upper bound on "normal" cells
75e5337592SStefano Zampini 
76412e9a14SMatthew G. Knepley   Level: developer
77e5337592SStefano Zampini 
78a1cb98faSBarry Smith   Note:
795ae96e2bSMatthew G. Knepley   This function requires that tensor cells are ordered last.
80a1cb98faSBarry Smith 
812827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()`
82e5337592SStefano Zampini @*/
83d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
84d71ae5a4SJacob Faibussowitsch {
855ae96e2bSMatthew G. Knepley   DMLabel         ctLabel;
865ae96e2bSMatthew G. Knepley   IS              valueIS;
875ae96e2bSMatthew G. Knepley   const PetscInt *ctypes;
885ae96e2bSMatthew G. Knepley   PetscInt        Nct, cS = PETSC_MAX_INT, cE = 0;
89e5337592SStefano Zampini 
90e5337592SStefano Zampini   PetscFunctionBegin;
919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
925ae96e2bSMatthew G. Knepley   PetscCall(DMLabelGetValueIS(ctLabel, &valueIS));
935ae96e2bSMatthew G. Knepley   PetscCall(ISGetLocalSize(valueIS, &Nct));
945ae96e2bSMatthew G. Knepley   PetscCall(ISGetIndices(valueIS, &ctypes));
955ae96e2bSMatthew G. Knepley   if (!Nct) cS = cE = 0;
965ae96e2bSMatthew G. Knepley   for (PetscInt t = 0; t < Nct; ++t) {
97c306944fSJed Brown     const DMPolytopeType ct = (DMPolytopeType)ctypes[t];
985ae96e2bSMatthew G. Knepley     PetscInt             ctS, ctE, ht;
995ae96e2bSMatthew G. Knepley 
1005ae96e2bSMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) {
1015ae96e2bSMatthew G. Knepley       // If any cells are not typed, just use all cells
1025ae96e2bSMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd));
1035ae96e2bSMatthew G. Knepley       break;
1045ae96e2bSMatthew G. Knepley     }
105c306944fSJed Brown     if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue;
1065ae96e2bSMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE));
1075ae96e2bSMatthew G. Knepley     if (ctS >= ctE) continue;
1085ae96e2bSMatthew G. Knepley     // Check that a point has the right height
1095ae96e2bSMatthew G. Knepley     PetscCall(DMPlexGetPointHeight(dm, ctS, &ht));
1105ae96e2bSMatthew G. Knepley     if (ht != height) continue;
1115ae96e2bSMatthew G. Knepley     cS = PetscMin(cS, ctS);
1125ae96e2bSMatthew G. Knepley     cE = PetscMax(cE, ctE);
1135ae96e2bSMatthew G. Knepley   }
1145ae96e2bSMatthew G. Knepley   PetscCall(ISDestroy(&valueIS));
115695799ffSMatthew G. Knepley   // Reset label for fast lookup
116695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
117412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
118412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120e5337592SStefano Zampini }
121e5337592SStefano Zampini 
1229c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft)
1239c600e38SMatt McGurn {
1249c600e38SMatt McGurn   PetscInt                 cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t;
1259c600e38SMatt McGurn   PetscInt                *sStart, *sEnd;
1269c600e38SMatt McGurn   PetscViewerVTKFieldType *ft;
1279c600e38SMatt McGurn   PetscInt                 vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1];
1289c600e38SMatt McGurn   DMLabel                  depthLabel, ctLabel;
1299c600e38SMatt McGurn 
1309c600e38SMatt McGurn   PetscFunctionBegin;
1319c600e38SMatt McGurn   /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */
1329c600e38SMatt McGurn   PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1));
1339c600e38SMatt McGurn   PetscCall(DMGetCoordinateDim(dm, &cdim));
1349c600e38SMatt McGurn   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1359c600e38SMatt McGurn   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1369c600e38SMatt McGurn   if (field >= 0) {
1379c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES]));
1389c600e38SMatt McGurn   } else {
1399c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES]));
1409c600e38SMatt McGurn   }
1419c600e38SMatt McGurn 
1429c600e38SMatt McGurn   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
1439c600e38SMatt McGurn   PetscCall(DMPlexGetDepth(dm, &depth));
1449c600e38SMatt McGurn   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
1459c600e38SMatt McGurn   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
1469c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1479c600e38SMatt McGurn     const DMPolytopeType ict = (DMPolytopeType)c;
1489c600e38SMatt McGurn     PetscInt             dep;
1499c600e38SMatt McGurn 
1509c600e38SMatt McGurn     if (ict == DM_POLYTOPE_FV_GHOST) continue;
1519c600e38SMatt McGurn     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1529c600e38SMatt McGurn     if (pStart >= 0) {
1539c600e38SMatt McGurn       PetscCall(DMLabelGetValue(depthLabel, cStart, &dep));
1549c600e38SMatt McGurn       if (dep != depth - cellHeight) continue;
1559c600e38SMatt McGurn     }
1569c600e38SMatt McGurn     if (field >= 0) {
1579c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c]));
1589c600e38SMatt McGurn     } else {
1599c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c]));
1609c600e38SMatt McGurn     }
1619c600e38SMatt McGurn   }
1629c600e38SMatt McGurn 
1639c600e38SMatt McGurn   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1649c600e38SMatt McGurn   *types = 0;
1659c600e38SMatt McGurn 
1669c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) {
1679c600e38SMatt McGurn     if (globalvcdof[c]) ++(*types);
1689c600e38SMatt McGurn   }
1699c600e38SMatt McGurn 
1709c600e38SMatt McGurn   PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft));
1719c600e38SMatt McGurn   t = 0;
1729c600e38SMatt McGurn   if (globalvcdof[DM_NUM_POLYTOPES]) {
1739c600e38SMatt McGurn     sStart[t] = vStart;
1749c600e38SMatt McGurn     sEnd[t]   = vEnd;
1759c600e38SMatt McGurn     ft[t]     = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
1769c600e38SMatt McGurn     ++t;
1779c600e38SMatt McGurn   }
1789c600e38SMatt McGurn 
1799c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1809c600e38SMatt McGurn     if (globalvcdof[c]) {
1819c600e38SMatt McGurn       const DMPolytopeType ict = (DMPolytopeType)c;
1829c600e38SMatt McGurn 
1839c600e38SMatt McGurn       PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1849c600e38SMatt McGurn       sStart[t] = cStart;
1859c600e38SMatt McGurn       sEnd[t]   = cEnd;
1869c600e38SMatt McGurn       ft[t]     = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD;
1879c600e38SMatt McGurn       ++t;
1889c600e38SMatt McGurn     }
1899c600e38SMatt McGurn   }
1909c600e38SMatt McGurn 
1914ad8454bSPierre Jolivet   if (!*types) {
1929c600e38SMatt McGurn     if (field >= 0) {
1939c600e38SMatt McGurn       const char *fieldname;
1949c600e38SMatt McGurn 
1959c600e38SMatt McGurn       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
1969c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
1979c600e38SMatt McGurn     } else {
1989c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
1999c600e38SMatt McGurn     }
2009c600e38SMatt McGurn   }
2019c600e38SMatt McGurn 
2029c600e38SMatt McGurn   *ssStart = sStart;
2039c600e38SMatt McGurn   *ssEnd   = sEnd;
2049c600e38SMatt McGurn   *sft     = ft;
2059c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2069c600e38SMatt McGurn }
2079c600e38SMatt McGurn 
2089c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft)
2099c600e38SMatt McGurn {
2109c600e38SMatt McGurn   PetscFunctionBegin;
2119c600e38SMatt McGurn   PetscCall(PetscFree3(*sStart, *sEnd, *ft));
2129c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2139c600e38SMatt McGurn }
2149c600e38SMatt McGurn 
215d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
216d71ae5a4SJacob Faibussowitsch {
217412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
218a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
2197e42fee7SMatthew G. Knepley 
2207e42fee7SMatthew G. Knepley   PetscFunctionBegin;
221e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
2229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
2239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
2259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
2267e42fee7SMatthew G. Knepley   if (field >= 0) {
2279566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
2289566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
2297e42fee7SMatthew G. Knepley   } else {
2309566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
2319566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
2327e42fee7SMatthew G. Knepley   }
233712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
234a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
2357e42fee7SMatthew G. Knepley     *sStart = vStart;
2367e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
237f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
2387e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
239a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
2407e42fee7SMatthew G. Knepley     *sStart = cStart;
2417e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
242f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
2437e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
244e630c359SToby Isaac   } else {
245e630c359SToby Isaac     if (field >= 0) {
246e630c359SToby Isaac       const char *fieldname;
247e630c359SToby Isaac 
2489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
24963a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
250e630c359SToby Isaac     } else {
25163a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
252e630c359SToby Isaac     }
253e630c359SToby Isaac   }
2543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2557e42fee7SMatthew G. Knepley }
2567e42fee7SMatthew G. Knepley 
2576913077dSMatthew G. Knepley /*@
2586913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
2596913077dSMatthew G. Knepley 
26020f4b53cSBarry Smith   Collective
2616913077dSMatthew G. Knepley 
2626913077dSMatthew G. Knepley   Input Parameters:
263a1cb98faSBarry Smith + dm     - The `DMPLEX` object
2646913077dSMatthew G. Knepley . n      - The number of vectors
2656913077dSMatthew G. Knepley . u      - The array of local vectors
266a1cb98faSBarry Smith - viewer - The `PetscViewer`
2676913077dSMatthew G. Knepley 
2686913077dSMatthew G. Knepley   Level: advanced
2696913077dSMatthew G. Knepley 
2701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
2716913077dSMatthew G. Knepley @*/
272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
273d71ae5a4SJacob Faibussowitsch {
2746913077dSMatthew G. Knepley   PetscDS            ds;
2756913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
2766913077dSMatthew G. Knepley   PetscDrawLG        lg;
2776913077dSMatthew G. Knepley   Vec                coordinates;
2786913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
2796913077dSMatthew G. Knepley   PetscReal         *vals;
2806913077dSMatthew G. Knepley   PetscInt          *Nc;
2816913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
2826913077dSMatthew G. Knepley   char             **names;
2836913077dSMatthew G. Knepley 
2846913077dSMatthew G. Knepley   PetscFunctionBegin;
2859566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
2869566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2879566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
2889566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2896913077dSMatthew G. Knepley 
2909566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2913ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
2929566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
2936913077dSMatthew G. Knepley 
2949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
2956913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
2966913077dSMatthew G. Knepley     const char *vname;
2976913077dSMatthew G. Knepley 
2989566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
2996913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
3006913077dSMatthew G. Knepley       PetscObject disc;
3016913077dSMatthew G. Knepley       const char *fname;
3026913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
3036913077dSMatthew G. Knepley 
3049566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
3056913077dSMatthew G. Knepley       /* TODO Create names for components */
3066913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
3079566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
308c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
309c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
310c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
3119566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
3126913077dSMatthew G. Knepley       }
3136913077dSMatthew G. Knepley     }
3146913077dSMatthew G. Knepley   }
3159566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
3166913077dSMatthew G. Knepley   /* Just add P_1 support for now */
3179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3199566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
3209566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
3216913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
3226913077dSMatthew G. Knepley     PetscScalar *x, *svals;
3236913077dSMatthew G. Knepley 
3249566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
3256913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
3269566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
3276913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
3286913077dSMatthew G. Knepley     }
3299566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
3306913077dSMatthew G. Knepley   }
3319566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
3329566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
3339566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
3349566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
3356913077dSMatthew G. Knepley 
3369566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
3379566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
3383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3396913077dSMatthew G. Knepley }
3406913077dSMatthew G. Knepley 
341d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
342d71ae5a4SJacob Faibussowitsch {
3436913077dSMatthew G. Knepley   DM dm;
3446913077dSMatthew G. Knepley 
3456913077dSMatthew G. Knepley   PetscFunctionBegin;
3469566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
3479566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
3483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3496913077dSMatthew G. Knepley }
3506913077dSMatthew G. Knepley 
351d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
352d71ae5a4SJacob Faibussowitsch {
353e412dcbdSMatthew G. Knepley   DM                 dm;
354d1df6f1dSMatthew G. Knepley   PetscSection       s;
355e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
356e412dcbdSMatthew G. Knepley   DM                 cdm;
357e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
358e412dcbdSMatthew G. Knepley   Vec                coordinates;
359c9c77995SMatthew G. Knepley   const PetscScalar *array;
360c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
361339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
3626913077dSMatthew G. Knepley   PetscBool          flg;
363d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
364e412dcbdSMatthew G. Knepley   const char        *name;
365339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
366e412dcbdSMatthew G. Knepley 
367e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
3689566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3699566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3709566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3719566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
3729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
3739566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
3749566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
3759566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
3769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
379e412dcbdSMatthew G. Knepley 
3809566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
3819566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
382e412dcbdSMatthew G. Knepley 
3839566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
384c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
3859566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
386e412dcbdSMatthew G. Knepley 
387d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
388d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
389d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
390d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
391d1df6f1dSMatthew G. Knepley     IS          fis;
392d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
393d1df6f1dSMatthew G. Knepley     const char *fname;
394d1df6f1dSMatthew G. Knepley 
3959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
3969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
397d1df6f1dSMatthew G. Knepley 
3989566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
399ad540459SPierre Jolivet     else prefix[0] = '\0';
400d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4019566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
4029566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
4039566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
4049566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
405d1df6f1dSMatthew G. Knepley     }
406d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
407d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
408d1df6f1dSMatthew G. Knepley 
4099566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
41063a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
41163a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
4129566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
413d1df6f1dSMatthew G. Knepley 
414d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
4159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
416339e3443SMatthew G. Knepley       if (!flg) {
4179566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
4189566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
419d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
420339e3443SMatthew G. Knepley       }
421c9c77995SMatthew G. Knepley 
4229566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
4239566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
424c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
4259566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
426e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
42799a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
428c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
429c9c77995SMatthew G. Knepley         PetscBool          isDG;
430e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
431e412dcbdSMatthew G. Knepley 
4329566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
433339e3443SMatthew G. Knepley         if (a) {
434d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
435339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
436339e3443SMatthew G. Knepley         } else {
437339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
438339e3443SMatthew G. Knepley           PetscInt     numVals, va;
439339e3443SMatthew G. Knepley 
4409566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
44163a3b9bcSJacob 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);
442d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
443d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
444d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
445d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
446339e3443SMatthew G. Knepley             break;
447d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
448d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
449d1df6f1dSMatthew 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]);
450d1df6f1dSMatthew G. Knepley             break;
451d71ae5a4SJacob Faibussowitsch           default:
452d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
453339e3443SMatthew G. Knepley           }
4549566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
455339e3443SMatthew G. Knepley         }
456c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
457e412dcbdSMatthew G. Knepley         switch (numCoords) {
458e412dcbdSMatthew G. Knepley         case 6:
4599edc3542SMatthew Knepley         case 12: /* Localized triangle */
4609566063dSJacob 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]));
461e412dcbdSMatthew G. Knepley           break;
462e412dcbdSMatthew G. Knepley         case 8:
4639edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
4649566063dSJacob 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]));
4659566063dSJacob 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]));
466e412dcbdSMatthew G. Knepley           break;
467d71ae5a4SJacob Faibussowitsch         default:
468d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
469e412dcbdSMatthew G. Knepley         }
470c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
471e412dcbdSMatthew G. Knepley       }
4729566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
4739566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
4749566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
4759566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
476d1df6f1dSMatthew G. Knepley     }
477d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4789566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
4799566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
4809566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
481d1df6f1dSMatthew G. Knepley     }
482d1df6f1dSMatthew G. Knepley   }
4833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
484e412dcbdSMatthew G. Knepley }
485e412dcbdSMatthew G. Knepley 
486d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
487d71ae5a4SJacob Faibussowitsch {
4886913077dSMatthew G. Knepley   DM        dm;
4896913077dSMatthew G. Knepley   PetscDraw draw;
4906913077dSMatthew G. Knepley   PetscInt  dim;
4916913077dSMatthew G. Knepley   PetscBool isnull;
4926913077dSMatthew G. Knepley 
4936913077dSMatthew G. Knepley   PetscFunctionBegin;
4949566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4959566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4963ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
4976913077dSMatthew G. Knepley 
4989566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
5006913077dSMatthew G. Knepley   switch (dim) {
501d71ae5a4SJacob Faibussowitsch   case 1:
502d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
503d71ae5a4SJacob Faibussowitsch     break;
504d71ae5a4SJacob Faibussowitsch   case 2:
505d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
506d71ae5a4SJacob Faibussowitsch     break;
507d71ae5a4SJacob Faibussowitsch   default:
508d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
5096913077dSMatthew G. Knepley   }
5103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5116913077dSMatthew G. Knepley }
5126913077dSMatthew G. Knepley 
513d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
514d71ae5a4SJacob Faibussowitsch {
515684b87d9SLisandro Dalcin   DM                      dm;
516684b87d9SLisandro Dalcin   Vec                     locv;
517684b87d9SLisandro Dalcin   const char             *name;
518684b87d9SLisandro Dalcin   PetscSection            section;
519684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
520e630c359SToby Isaac   PetscInt                numFields;
521684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
522684b87d9SLisandro Dalcin 
523684b87d9SLisandro Dalcin   PetscFunctionBegin;
5249566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
5259566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
5269566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
5279566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
5289566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
5299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
5309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
531e630c359SToby Isaac   if (!numFields) {
5329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
5339566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
534e630c359SToby Isaac   } else {
535e630c359SToby Isaac     PetscInt f;
536e630c359SToby Isaac 
537e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
5389566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
539e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
5409566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
5419566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
542e630c359SToby Isaac     }
5439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
544e630c359SToby Isaac   }
5453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546684b87d9SLisandro Dalcin }
547684b87d9SLisandro Dalcin 
548d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
549d71ae5a4SJacob Faibussowitsch {
550552f7358SJed Brown   DM        dm;
5515f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
552552f7358SJed Brown 
553552f7358SJed Brown   PetscFunctionBegin;
5549566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
55528b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5605f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5615f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
562684b87d9SLisandro Dalcin     PetscInt    i, numFields;
563684b87d9SLisandro Dalcin     PetscObject fe;
564ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
565684b87d9SLisandro Dalcin     Vec         locv = v;
566684b87d9SLisandro Dalcin     const char *name;
567684b87d9SLisandro Dalcin     PetscInt    step;
568684b87d9SLisandro Dalcin     PetscReal   time;
569ef31f671SMatthew G. Knepley 
5709566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
571684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
5729566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
5739371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
5749371c9d4SSatish Balay         fem = PETSC_TRUE;
5759371c9d4SSatish Balay         break;
5769371c9d4SSatish Balay       }
577ef31f671SMatthew G. Knepley     }
578684b87d9SLisandro Dalcin     if (fem) {
579798534f6SMatthew G. Knepley       PetscObject isZero;
580798534f6SMatthew G. Knepley 
5819566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
5829566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
5839566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
5849566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5859566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5869566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
5879566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
5889566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
589ef31f671SMatthew G. Knepley     }
590552f7358SJed Brown     if (isvtk) {
5919566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
592b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
593b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5949566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
595b136c2c9SMatthew G. Knepley #else
596b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
597b136c2c9SMatthew G. Knepley #endif
598f13a32a3SMatthew G. Knepley     } else if (isdraw) {
5999566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
600684b87d9SLisandro Dalcin     } else if (isglvis) {
6019566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
6029566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
6039566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
6045f34f2dcSJed Brown     } else if (iscgns) {
6055f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
6065f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
6075f34f2dcSJed Brown #else
6085f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
6095f34f2dcSJed Brown #endif
610684b87d9SLisandro Dalcin     }
611798534f6SMatthew G. Knepley     if (fem) {
6129566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6139566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
614798534f6SMatthew G. Knepley     }
615552f7358SJed Brown   } else {
616684b87d9SLisandro Dalcin     PetscBool isseq;
617684b87d9SLisandro Dalcin 
6189566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6199566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6209566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
621552f7358SJed Brown   }
6223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
623552f7358SJed Brown }
624552f7358SJed Brown 
625d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
626d71ae5a4SJacob Faibussowitsch {
627552f7358SJed Brown   DM        dm;
6285f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
629552f7358SJed Brown 
630552f7358SJed Brown   PetscFunctionBegin;
6319566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
6375f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
6389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6395f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
640552f7358SJed Brown     Vec         locv;
641798534f6SMatthew G. Knepley     PetscObject isZero;
642552f7358SJed Brown     const char *name;
643552f7358SJed Brown 
6449566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
6459566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
6479566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6489566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6499566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6509566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6519566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
6529566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6539566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
654b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
655b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6569566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
657b136c2c9SMatthew G. Knepley #else
658b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
659b136c2c9SMatthew G. Knepley #endif
6606823f3c5SBlaise Bourdin   } else if (isexodusii) {
6616823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6629566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
6636823f3c5SBlaise Bourdin #else
6646823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6656823f3c5SBlaise Bourdin #endif
666552f7358SJed Brown   } else {
667684b87d9SLisandro Dalcin     PetscBool isseq;
668684b87d9SLisandro Dalcin 
6699566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6709566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6719566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
672552f7358SJed Brown   }
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
674552f7358SJed Brown }
675552f7358SJed Brown 
676d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
677d71ae5a4SJacob Faibussowitsch {
678d930f514SMatthew G. Knepley   DM                dm;
679d930f514SMatthew G. Knepley   MPI_Comm          comm;
680d930f514SMatthew G. Knepley   PetscViewerFormat format;
681d930f514SMatthew G. Knepley   Vec               v;
682d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
683d930f514SMatthew G. Knepley 
684d930f514SMatthew G. Knepley   PetscFunctionBegin;
6859566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
6869566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
68728b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6889566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
691d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
692a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
693a8ad634aSStefano Zampini     /* this need a better fix */
694a8ad634aSStefano Zampini     if (dm->useNatural) {
695a8ad634aSStefano Zampini       if (dm->sfNatural) {
696d930f514SMatthew G. Knepley         const char *vecname;
697d930f514SMatthew G. Knepley         PetscInt    n, nroots;
698d930f514SMatthew G. Knepley 
6999566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
7009566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
701d930f514SMatthew G. Knepley         if (n == nroots) {
702f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
7039566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
7049566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
7059566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7069566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
707d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
708d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
709a8ad634aSStefano Zampini     } else v = originalv;
710a8ad634aSStefano Zampini   } else v = originalv;
711a8ad634aSStefano Zampini 
712d930f514SMatthew G. Knepley   if (ishdf5) {
713d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7149566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
715d930f514SMatthew G. Knepley #else
716d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
717d930f514SMatthew G. Knepley #endif
718d930f514SMatthew G. Knepley   } else if (isvtk) {
719d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
720d930f514SMatthew G. Knepley   } else {
721d930f514SMatthew G. Knepley     PetscBool isseq;
722d930f514SMatthew G. Knepley 
7239566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7249566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
7259566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
726d930f514SMatthew G. Knepley   }
727f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
7283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
729d930f514SMatthew G. Knepley }
730d930f514SMatthew G. Knepley 
731d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
732d71ae5a4SJacob Faibussowitsch {
7332c40f234SMatthew G. Knepley   DM        dm;
7342c40f234SMatthew G. Knepley   PetscBool ishdf5;
7352c40f234SMatthew G. Knepley 
7362c40f234SMatthew G. Knepley   PetscFunctionBegin;
7379566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
73828b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7402c40f234SMatthew G. Knepley   if (ishdf5) {
7412c40f234SMatthew G. Knepley     DM          dmBC;
7422c40f234SMatthew G. Knepley     Vec         gv;
7432c40f234SMatthew G. Knepley     const char *name;
7442c40f234SMatthew G. Knepley 
7459566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
7469566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
7479566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
7489566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
7499566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
7509566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
7519566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
7529566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
7531baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7552c40f234SMatthew G. Knepley }
7562c40f234SMatthew G. Knepley 
757d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
758d71ae5a4SJacob Faibussowitsch {
7592c40f234SMatthew G. Knepley   DM        dm;
7606823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
7612c40f234SMatthew G. Knepley 
7622c40f234SMatthew G. Knepley   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
76428b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
7672c40f234SMatthew G. Knepley   if (ishdf5) {
768878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7699566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
770b136c2c9SMatthew G. Knepley #else
771b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
772878b459fSMatthew G. Knepley #endif
7736823f3c5SBlaise Bourdin   } else if (isexodusii) {
7746823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
7759566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
7766823f3c5SBlaise Bourdin #else
7776823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
7786823f3c5SBlaise Bourdin #endif
7791baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
781552f7358SJed Brown }
782552f7358SJed Brown 
783d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
784d71ae5a4SJacob Faibussowitsch {
785d930f514SMatthew G. Knepley   DM                dm;
786d930f514SMatthew G. Knepley   PetscViewerFormat format;
787d930f514SMatthew G. Knepley   PetscBool         ishdf5;
788d930f514SMatthew G. Knepley 
789d930f514SMatthew G. Knepley   PetscFunctionBegin;
7909566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
79128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7929566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
794d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
795a8ad634aSStefano Zampini     if (dm->useNatural) {
796d930f514SMatthew G. Knepley       if (dm->sfNatural) {
797d930f514SMatthew G. Knepley         if (ishdf5) {
798d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
799d930f514SMatthew G. Knepley           Vec         v;
800d930f514SMatthew G. Knepley           const char *vecname;
801d930f514SMatthew G. Knepley 
802f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
8039566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
8049566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
8059566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
8069566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
8079566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
808f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
809d930f514SMatthew G. Knepley #else
810d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
811d930f514SMatthew G. Knepley #endif
812d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
813d930f514SMatthew G. Knepley       }
8141baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
815d930f514SMatthew G. Knepley   }
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817d930f514SMatthew G. Knepley }
818d930f514SMatthew G. Knepley 
819d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
820d71ae5a4SJacob Faibussowitsch {
821731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
822731e8ddeSMatthew G. Knepley   Vec                coordinates;
823ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
824731e8ddeSMatthew G. Knepley   const char        *name[4];
825731e8ddeSMatthew G. Knepley   const PetscScalar *a;
826731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
827731e8ddeSMatthew G. Knepley 
828731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
8299566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
8339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
8349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8369566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
837731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
838731e8ddeSMatthew G. Knepley   name[1]       = "edge";
839731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
840731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
841731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
842731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
843ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
844731e8ddeSMatthew G. Knepley 
8459566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
84663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
8479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
849731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
850731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
851731e8ddeSMatthew G. Knepley 
852731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
8539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
854731e8ddeSMatthew G. Knepley       if (!dof) continue;
8559566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
8569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
85763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
858731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
8599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
860731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
8619566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
8629566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
863731e8ddeSMatthew G. Knepley         }
8649566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
865731e8ddeSMatthew G. Knepley       }
8669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
867731e8ddeSMatthew G. Knepley     }
8689566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
870731e8ddeSMatthew G. Knepley   }
8719566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
8723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
873731e8ddeSMatthew G. Knepley }
874731e8ddeSMatthew G. Knepley 
8759371c9d4SSatish Balay typedef enum {
8769371c9d4SSatish Balay   CS_CARTESIAN,
8779371c9d4SSatish Balay   CS_POLAR,
8789371c9d4SSatish Balay   CS_CYLINDRICAL,
8799371c9d4SSatish Balay   CS_SPHERICAL
8809371c9d4SSatish Balay } CoordSystem;
88119ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
88219ad8254SMatthew G. Knepley 
883d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
884d71ae5a4SJacob Faibussowitsch {
88519ad8254SMatthew G. Knepley   PetscInt i;
88619ad8254SMatthew G. Knepley 
88719ad8254SMatthew G. Knepley   PetscFunctionBegin;
88819ad8254SMatthew G. Knepley   if (dim > 3) {
8899566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
89019ad8254SMatthew G. Knepley   } else {
891bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
89219ad8254SMatthew G. Knepley 
89319ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
89419ad8254SMatthew G. Knepley     switch (cs) {
8959371c9d4SSatish Balay     case CS_CARTESIAN:
8969371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
8979371c9d4SSatish Balay       break;
89819ad8254SMatthew G. Knepley     case CS_POLAR:
89963a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
90019ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90119ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90219ad8254SMatthew G. Knepley       break;
90319ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
90463a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
90519ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90619ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90719ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
90819ad8254SMatthew G. Knepley       break;
90919ad8254SMatthew G. Knepley     case CS_SPHERICAL:
91063a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
91119ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
91219ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
91319ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
91419ad8254SMatthew G. Knepley       break;
91519ad8254SMatthew G. Knepley     }
9169566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
91719ad8254SMatthew G. Knepley   }
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91919ad8254SMatthew G. Knepley }
92019ad8254SMatthew G. Knepley 
921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
922d71ae5a4SJacob Faibussowitsch {
923552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
9246858538eSMatthew G. Knepley   DM                cdm, cdmCell;
9256858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
9266858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
927552f7358SJed Brown   PetscViewerFormat format;
928552f7358SJed Brown 
929552f7358SJed Brown   PetscFunctionBegin;
9309566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
931552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
932552f7358SJed Brown     const char *name;
933f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
9349318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
935552f7358SJed Brown     PetscMPIInt rank, size;
936552f7358SJed Brown 
9379f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9389f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9399f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9409f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9419f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9429f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9459566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
9469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
9489566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
95063a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
95163a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
95263a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
95363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
9549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
95563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
956552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
957552f7358SJed Brown       PetscInt dof, off, s;
958552f7358SJed Brown 
9599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
9609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
96148a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
962552f7358SJed Brown     }
9639566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
96463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
96563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
966552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
967552f7358SJed Brown       PetscInt dof, off, c;
968552f7358SJed Brown 
9699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
9709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
97148a46eb9SPierre 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]));
972552f7358SJed Brown     }
9739566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
9749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9753d2e540fSStefano Zampini     if (coordSection && coordinates) {
97619ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
9776858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
9786858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
97919ad8254SMatthew G. Knepley       PetscMPIInt        rank;
98019ad8254SMatthew G. Knepley       const char        *name;
98119ad8254SMatthew G. Knepley 
9829566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
9839566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
9849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
98563a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
9869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
9876858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
9886858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
9896858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
9906858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
9919566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
99263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
99363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
9949566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
99519ad8254SMatthew G. Knepley 
9969566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
9976858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
9989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
9999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
100019ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
100119ad8254SMatthew G. Knepley         PetscInt dof, off;
100219ad8254SMatthew G. Knepley 
10036858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
10049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
10059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
10066858538eSMatthew G. Knepley           if (dof) {
100763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10089566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
10099566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
101019ad8254SMatthew G. Knepley           }
10116858538eSMatthew G. Knepley         }
10126858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
10136858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
10146858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
10156858538eSMatthew G. Knepley           if (dof) {
10166858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10176858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
10186858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
10196858538eSMatthew G. Knepley           }
10206858538eSMatthew G. Knepley         }
10216858538eSMatthew G. Knepley       }
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
10239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
10249566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
10256858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
10263d2e540fSStefano Zampini     }
10279566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10289566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
10299318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
10309318fe57SMatthew G. Knepley       DMLabel     label;
10319318fe57SMatthew G. Knepley       PetscBool   isdepth;
10329318fe57SMatthew G. Knepley       const char *name;
10339318fe57SMatthew G. Knepley 
10349566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
10359566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
10369318fe57SMatthew G. Knepley       if (isdepth) continue;
10379566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
10389566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
10399318fe57SMatthew G. Knepley     }
1040552f7358SJed Brown     if (size > 1) {
1041552f7358SJed Brown       PetscSF sf;
1042552f7358SJed Brown 
10439566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
10449566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
1045552f7358SJed Brown     }
10464e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
10479566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1048552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
10490588280cSMatthew G. Knepley     const char  *name, *color;
10500588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
10510588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
1052fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
1053552f7358SJed Brown     PetscReal    scale      = 2.0;
105478081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
1055b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
10560588280cSMatthew G. Knepley     double       tcoords[3];
1057552f7358SJed Brown     PetscScalar *coords;
1058b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
1059552f7358SJed Brown     PetscMPIInt  rank, size;
10600588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
1061b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
1062fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
1063fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
1064552f7358SJed Brown 
10659f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
10669f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
10679f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10689f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
10699f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
10709f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
10719566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
10729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
10739566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10740588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
10750588280cSMatthew G. Knepley     numColors  = 10;
10760588280cSMatthew G. Knepley     numLColors = 10;
10779566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
10789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
10799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
10809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
1081b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
1082b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
1083b7f6ffafSMatthew G. Knepley     n = 4;
10849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
10851dca8a05SBarry 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);
1086bd3611e6SMatthew G. Knepley     n = 4;
10879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
10881dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
10899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
10900588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
10919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
10920588280cSMatthew G. Knepley     if (!useColors) {
10930588280cSMatthew G. Knepley       numColors = 3;
10949566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
10950588280cSMatthew G. Knepley     }
10969566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
10970588280cSMatthew G. Knepley     if (!useColors) {
10980588280cSMatthew G. Knepley       numLColors = 4;
10999566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
11000588280cSMatthew G. Knepley     }
11019566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
1102b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
11039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
11041dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1105202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
11069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1107fe1cc32dSStefano Zampini 
1108fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
11099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
11109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
11119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
11129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1113fe1cc32dSStefano Zampini     if (lflg) {
1114fe1cc32dSStefano Zampini       DMLabel lbl;
1115fe1cc32dSStefano Zampini 
11169566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1117fe1cc32dSStefano Zampini       if (lbl) {
1118fe1cc32dSStefano Zampini         PetscInt val, defval;
1119fe1cc32dSStefano Zampini 
11209566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
11219566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1122fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1123fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1124fe1cc32dSStefano Zampini           PetscInt  closureSize;
1125fe1cc32dSStefano Zampini 
11269566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1127fe1cc32dSStefano Zampini           if (val == defval) continue;
1128fe1cc32dSStefano Zampini 
11299566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
113048a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
11319566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1132fe1cc32dSStefano Zampini         }
1133fe1cc32dSStefano Zampini       }
1134fe1cc32dSStefano Zampini     }
1135fe1cc32dSStefano Zampini 
11369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
11379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
11389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
11399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
11400588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1141552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1142552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1143552f7358SJed Brown \\usetikzlibrary{arrows}\n\
11445f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
11450588280cSMatthew G. Knepley     if (size > 1) {
11469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1147770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
114863a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
114963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1150770b213bSMatthew G Knepley       }
11519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
11520588280cSMatthew G. Knepley     }
1153b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1154b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1155b7f6ffafSMatthew G. Knepley 
115663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
115763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
115863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
11599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
116063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
116163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
11629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
116363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
116463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
116563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
116663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
11679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1168b7f6ffafSMatthew G. Knepley     }
11699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1170fe1cc32dSStefano Zampini 
1171552f7358SJed Brown     /* Plot vertices */
11729566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
11739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1174552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1175552f7358SJed Brown       PetscInt  off, dof, d;
11760588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1177552f7358SJed Brown 
1178fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
11799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
11809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
11819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
118263a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
11830588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11840588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1185c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
11860588280cSMatthew G. Knepley       }
11870588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
11889371c9d4SSatish Balay       if (dim == 3) {
11899371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
11909371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
11919371c9d4SSatish Balay         tcoords[2]    = -tmp;
11929371c9d4SSatish Balay       }
1193552f7358SJed Brown       for (d = 0; d < dof; ++d) {
11949566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11959566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1196552f7358SJed Brown       }
1197b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1198b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
11990588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
12000588280cSMatthew G. Knepley         PetscInt val;
12019566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
12029371c9d4SSatish Balay         if (val >= 0) {
12039371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12049371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12059371c9d4SSatish Balay           break;
12069371c9d4SSatish Balay         }
12070588280cSMatthew G. Knepley       }
1208b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
120963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1210b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
121163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
12121baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1213552f7358SJed Brown     }
12149566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12159566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1216b7f6ffafSMatthew G. Knepley     /* Plot edges */
1217b7f6ffafSMatthew G. Knepley     if (plotEdges) {
12189566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
12199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1220b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1221b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1222b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1223b7f6ffafSMatthew G. Knepley 
1224b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
12259566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
122663a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
12279566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
12289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
12299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
12309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
12319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1232b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1233b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1234b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1235b7f6ffafSMatthew G. Knepley         }
1236b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12379371c9d4SSatish Balay         if (dim == 3) {
12389371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12399371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12409371c9d4SSatish Balay           tcoords[2]    = -tmp;
12419371c9d4SSatish Balay         }
1242b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12439566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12449566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1245b7f6ffafSMatthew G. Knepley         }
1246b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1247b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1248b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1249b7f6ffafSMatthew G. Knepley           PetscInt val;
1250bd3611e6SMatthew G. Knepley           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12519371c9d4SSatish Balay           if (val >= 0) {
12529371c9d4SSatish Balay             color = lcolors[l % numLColors];
12539371c9d4SSatish Balay             break;
12549371c9d4SSatish Balay           }
1255b7f6ffafSMatthew G. Knepley         }
125663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1257b7f6ffafSMatthew G. Knepley       }
12589566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
12599566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
12609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1261b7f6ffafSMatthew G. Knepley     }
1262846a3e8bSMatthew G. Knepley     /* Plot cells */
1263b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1264846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1265846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1266846a3e8bSMatthew G. Knepley 
1267fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1268846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1269846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1270846a3e8bSMatthew G. Knepley           PetscInt val;
12719566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12729371c9d4SSatish Balay           if (val >= 0) {
12739371c9d4SSatish Balay             color = lcolors[l % numLColors];
12749371c9d4SSatish Balay             break;
12759371c9d4SSatish Balay           }
1276846a3e8bSMatthew G. Knepley         }
12779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
127863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1279846a3e8bSMatthew G. Knepley       }
1280846a3e8bSMatthew G. Knepley     } else {
1281b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1282846a3e8bSMatthew G. Knepley 
1283b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1284b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1285fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
12869566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1287c306944fSJed Brown         if (DMPolytopeTypeIsHybrid(ct)) {
1288b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1289b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1290b7f6ffafSMatthew G. Knepley 
12919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
12929566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1293b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1294b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1295b7f6ffafSMatthew G. Knepley 
12969566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
129763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank));
1298b7f6ffafSMatthew G. Knepley           }
1299b7f6ffafSMatthew G. Knepley         } else {
1300b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1301b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1302b7f6ffafSMatthew G. Knepley 
13039566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1304846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1305846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1306846a3e8bSMatthew G. Knepley 
1307b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1308846a3e8bSMatthew G. Knepley           }
13099566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1310b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1311b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1312b7f6ffafSMatthew G. Knepley 
1313b7f6ffafSMatthew G. Knepley             if (v > 0) {
1314b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1315b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1316b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1317b7f6ffafSMatthew G. Knepley 
13189371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
13199371c9d4SSatish Balay                 endpoints[1] = vertex;
13209566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
132163a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
132263a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
13239566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
13241baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1325b7f6ffafSMatthew G. Knepley             }
132663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1327b7f6ffafSMatthew G. Knepley           }
13289566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
13299566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1330846a3e8bSMatthew G. Knepley         }
1331846a3e8bSMatthew G. Knepley       }
1332b7f6ffafSMatthew G. Knepley     }
1333846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1334846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1335846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1336c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1337c713ec31SMatthew G. Knepley       const PetscScalar *array;
1338c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1339c713ec31SMatthew G. Knepley       PetscBool          isDG;
1340846a3e8bSMatthew G. Knepley 
1341fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1342c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1343c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1344c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
13459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1346c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1347c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1348c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1349846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1350846a3e8bSMatthew G. Knepley         }
1351846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
13529371c9d4SSatish Balay         if (cdim == 3) {
13539371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
13549371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
13559371c9d4SSatish Balay           tcoords[2]    = -tmp;
13569371c9d4SSatish Balay         }
1357ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1358846a3e8bSMatthew G. Knepley       }
1359ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1360c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1361c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
13629566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
13639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1364846a3e8bSMatthew G. Knepley       }
1365b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1366b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1367846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1368846a3e8bSMatthew G. Knepley         PetscInt val;
13699566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
13709371c9d4SSatish Balay         if (val >= 0) {
13719371c9d4SSatish Balay           color     = lcolors[l % numLColors];
13729371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
13739371c9d4SSatish Balay           break;
13749371c9d4SSatish Balay         }
1375846a3e8bSMatthew G. Knepley       }
1376b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
137763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1378b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
137963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
13801baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1381846a3e8bSMatthew G. Knepley     }
1382b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1383b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
13849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
13859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
13869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
13889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1389552f7358SJed Brown 
1390b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
13919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
13929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
13939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
13959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1396b7f6ffafSMatthew G. Knepley 
1397b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
13989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
13999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
14009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
14019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
14029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1403b7f6ffafSMatthew G. Knepley 
1404b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1405b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1406b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1407b7f6ffafSMatthew G. Knepley 
14089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
14099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
141048a46eb9SPierre Jolivet         for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
14110588280cSMatthew G. Knepley       }
14120588280cSMatthew G. Knepley     }
14139566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
14149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
14159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
141663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
14179566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
14189566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
14199566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
14209566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
14219566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
14220f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
14230f7d6e4aSStefano Zampini     Vec                    cown, acown;
14240f7d6e4aSStefano Zampini     VecScatter             sct;
14250f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
14260f7d6e4aSStefano Zampini     IS                     gid, acis;
14270f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
14280f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
14290f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
14300f7d6e4aSStefano Zampini     const PetscInt        *idxs;
14310f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
14320f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
14330f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
14340f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
14350f7d6e4aSStefano Zampini 
14369566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1438b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
14399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
14400f7d6e4aSStefano Zampini #endif
14410f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
14429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
14439566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
14440f7d6e4aSStefano Zampini       d1 = 0;
14459566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
14460f7d6e4aSStefano Zampini       nid = d2;
14479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
14489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
14499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
14500f7d6e4aSStefano Zampini     } else nid = 0.0;
14510f7d6e4aSStefano Zampini 
14520f7d6e4aSStefano Zampini     /* Get connectivity */
14539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14549566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
14550f7d6e4aSStefano Zampini 
14560f7d6e4aSStefano Zampini     /* filter overlapped local cells */
14579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
14589566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
14599566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
14609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
14610f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
14620f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
14630f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
14640f7d6e4aSStefano Zampini     }
14659566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
146663a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
14679566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14689566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
14690f7d6e4aSStefano Zampini 
14700f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
14719566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
14729566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
14739566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
14749566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
14750f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
14769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
14779566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
14789566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14799566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14809566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
14819566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
14829566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
14830f7d6e4aSStefano Zampini 
14840f7d6e4aSStefano Zampini     /* compute edgeCut */
14850f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
14869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
14879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
14889566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
14899566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14909566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
14910f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
14920f7d6e4aSStefano Zampini       PetscInt totl;
14930f7d6e4aSStefano Zampini 
14940f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
14959566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
14960f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
14970f7d6e4aSStefano Zampini         if (work[i] < 0) {
14980f7d6e4aSStefano Zampini           ect += 1;
14990f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
15000f7d6e4aSStefano Zampini         }
15010f7d6e4aSStefano Zampini       }
15020f7d6e4aSStefano Zampini     }
15039566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
15049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
15050f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
15060f7d6e4aSStefano Zampini     lm[1] = -numVertices;
15071c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
150863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0]));
15090f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
15100f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
15110f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
15121c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
151363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1514b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
1515f4f49eeaSPierre 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.));
15160f7d6e4aSStefano Zampini #else
151763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
15180f7d6e4aSStefano Zampini #endif
15199566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
15209566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
15219566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
15229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1523552f7358SJed Brown   } else {
1524412e9a14SMatthew G. Knepley     const char    *name;
1525d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1526412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1527d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1528ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
15299318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1530412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1531412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1532552f7358SJed Brown 
15339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
15359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
15369566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
15379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
15389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
153963a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
154063a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
154163a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
15429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
15431c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
15442827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd));
1545d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
15469566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
15479566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1548412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1549412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1550412e9a14SMatthew G. Knepley 
15519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
15529566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1553412e9a14SMatthew G. Knepley       ict = ct0;
15549566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1555412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1556412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1557412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1558412e9a14SMatthew G. Knepley 
15599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1560412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1561412e9a14SMatthew G. Knepley         else ++Nc[1];
1562412e9a14SMatthew G. Knepley       }
1563ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
15649566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15659566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
15669566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
156763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1568834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1569dd400576SPatrick Sanan           if (rank == 0) {
157063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
157163a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
157263a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1573834065abSMatthew G. Knepley           }
1574cbb7f117SMark Adams         }
1575ca7bf7eeSMatthew G. Knepley       } else {
1576ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1577ca7bf7eeSMatthew G. Knepley 
15789371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
15799371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
15809566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15819371c9d4SSatish Balay         locMinMax[0] = Nc[1];
15829371c9d4SSatish Balay         locMinMax[1] = Nc[1];
15839566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1584ca7bf7eeSMatthew G. Knepley         if (d == depth) {
15859371c9d4SSatish Balay           locMinMax[0] = gcNum;
15869371c9d4SSatish Balay           locMinMax[1] = gcNum;
15879566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1588ca7bf7eeSMatthew G. Knepley         }
158963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
15909566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15919566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
15929566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1593ca7bf7eeSMatthew G. Knepley       }
15949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1595552f7358SJed Brown     }
15969566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
15979318fe57SMatthew G. Knepley     {
15989318fe57SMatthew G. Knepley       const PetscReal *maxCell;
15999318fe57SMatthew G. Knepley       const PetscReal *L;
16006858538eSMatthew G. Knepley       PetscBool        localized;
16019318fe57SMatthew G. Knepley 
16024fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
16039566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
16046858538eSMatthew G. Knepley       if (L || localized) {
16056858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
16069566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
16076858538eSMatthew G. Knepley         if (L) {
16086858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
16099318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
16106858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
16116858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
16129318fe57SMatthew G. Knepley           }
16136858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
16146858538eSMatthew G. Knepley         }
16156858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
16169566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16179318fe57SMatthew G. Knepley       }
16189318fe57SMatthew G. Knepley     }
16199566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
16209566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1621a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1622a57dd577SMatthew G Knepley       DMLabel         label;
1623a57dd577SMatthew G Knepley       const char     *name;
1624a57dd577SMatthew G Knepley       IS              valueIS;
1625a57dd577SMatthew G Knepley       const PetscInt *values;
1626a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1627a57dd577SMatthew G Knepley 
16289566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
16299566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
16309566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
163163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
16329566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
16339566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
16349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1635a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1636a57dd577SMatthew G Knepley         PetscInt size;
1637a57dd577SMatthew G Knepley 
16389566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
16399566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
164063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1641a57dd577SMatthew G Knepley       }
16429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
16439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16449566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
16459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1646a57dd577SMatthew G Knepley     }
1647c1cad2e7SMatthew G. Knepley     {
1648c1cad2e7SMatthew G. Knepley       char    **labelNames;
1649c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1650c1cad2e7SMatthew G. Knepley       PetscBool flg;
1651c1cad2e7SMatthew G. Knepley 
16529566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
16539566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1654c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1655c1cad2e7SMatthew G. Knepley         DMLabel label;
1656c1cad2e7SMatthew G. Knepley 
16579566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1658c1cad2e7SMatthew G. Knepley         if (flg) {
16599566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
16609566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1661c1cad2e7SMatthew G. Knepley         }
16629566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1663c1cad2e7SMatthew G. Knepley       }
16649566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1665c1cad2e7SMatthew G. Knepley     }
166634aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
166734aa8a36SMatthew G. Knepley     if (dm->Nf) {
166834aa8a36SMatthew G. Knepley       PetscInt f;
166934aa8a36SMatthew G. Knepley 
167034aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
167134aa8a36SMatthew G. Knepley         const char *name;
167234aa8a36SMatthew G. Knepley 
16739566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
16749566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
16759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
16769566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
167734aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
16789566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
16799566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
168034aa8a36SMatthew G. Knepley         } else {
16819566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
16829566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
168334aa8a36SMatthew G. Knepley         }
16849566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
168534aa8a36SMatthew G. Knepley       }
168634aa8a36SMatthew G. Knepley     }
16879566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
16888e7ff633SMatthew G. Knepley     if (cdm) {
16899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
16909f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
16919566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
16929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
16938e7ff633SMatthew G. Knepley     }
1694552f7358SJed Brown   }
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696552f7358SJed Brown }
1697552f7358SJed Brown 
1698d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1699d71ae5a4SJacob Faibussowitsch {
1700e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1701e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1702a12d352dSMatthew G. Knepley   PetscInt       cdim;
1703e5c487bfSMatthew G. Knepley 
1704e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
17079566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1708e5c487bfSMatthew G. Knepley   switch (ct) {
1709a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1710a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1711a12d352dSMatthew G. Knepley     switch (cdim) {
17129371c9d4SSatish Balay     case 1: {
1713a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1714a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1715a12d352dSMatthew G. Knepley 
17169566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
17179566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
17189566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
17199371c9d4SSatish Balay     } break;
17209371c9d4SSatish Balay     case 2: {
1721a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1722a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1723a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1724a12d352dSMatthew G. Knepley 
17259566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17269566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK));
17279566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK));
17289371c9d4SSatish Balay     } break;
1729d71ae5a4SJacob Faibussowitsch     default:
1730d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1731a12d352dSMatthew G. Knepley     }
1732a12d352dSMatthew G. Knepley     break;
1733e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
17349371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17369566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17379566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1738e5c487bfSMatthew G. Knepley     break;
1739e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
17409371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17419371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17459566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1746e5c487bfSMatthew G. Knepley     break;
17479f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
17489f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17499f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17509f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17519f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17529f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17539f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
17549f4ada15SMatthew G. Knepley     break;
1755d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1756d71ae5a4SJacob Faibussowitsch     break;
1757d71ae5a4SJacob Faibussowitsch   default:
1758d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1759e5c487bfSMatthew G. Knepley   }
17603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1761e5c487bfSMatthew G. Knepley }
1762e5c487bfSMatthew G. Knepley 
1763c5aedaa3SMatthew 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[])
1764d71ae5a4SJacob Faibussowitsch {
1765e5c487bfSMatthew G. Knepley   PetscReal   centroid[2] = {0., 0.};
1766e5c487bfSMatthew G. Knepley   PetscMPIInt rank;
1767c5aedaa3SMatthew G. Knepley   PetscInt    fillColor;
1768e5c487bfSMatthew G. Knepley 
1769e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1771e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1772c5aedaa3SMatthew G. Knepley   for (PetscInt v = 0; v < Nv; ++v) {
1773c5aedaa3SMatthew G. Knepley     centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv;
1774c5aedaa3SMatthew G. Knepley     centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv;
17759371c9d4SSatish Balay   }
1776c5aedaa3SMatthew G. Knepley   for (PetscInt e = 0; e < Nv; ++e) {
1777e5c487bfSMatthew G. Knepley     refCoords[0] = refVertices[e * 2 + 0];
1778e5c487bfSMatthew G. Knepley     refCoords[1] = refVertices[e * 2 + 1];
1779c5aedaa3SMatthew G. Knepley     for (PetscInt d = 1; d <= edgeDiv; ++d) {
1780c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv;
1781c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv;
1782e5c487bfSMatthew G. Knepley     }
17839566063dSJacob Faibussowitsch     PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1784c5aedaa3SMatthew G. Knepley     for (PetscInt d = 0; d < edgeDiv; ++d) {
17859566063dSJacob 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));
17869566063dSJacob 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));
1787e5c487bfSMatthew G. Knepley     }
1788e5c487bfSMatthew G. Knepley   }
1789c5aedaa3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1790c5aedaa3SMatthew G. Knepley }
1791c5aedaa3SMatthew G. Knepley 
1792c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1793c5aedaa3SMatthew G. Knepley {
1794c5aedaa3SMatthew G. Knepley   DMPolytopeType ct;
1795c5aedaa3SMatthew G. Knepley 
1796c5aedaa3SMatthew G. Knepley   PetscFunctionBegin;
1797c5aedaa3SMatthew G. Knepley   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1798c5aedaa3SMatthew G. Knepley   switch (ct) {
1799c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE: {
1800c5aedaa3SMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1801c5aedaa3SMatthew G. Knepley 
1802c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords));
1803c5aedaa3SMatthew G. Knepley   } break;
1804c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL: {
1805c5aedaa3SMatthew G. Knepley     PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.};
1806c5aedaa3SMatthew G. Knepley 
1807c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords));
18089371c9d4SSatish Balay   } break;
1809d71ae5a4SJacob Faibussowitsch   default:
1810d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1811e5c487bfSMatthew G. Knepley   }
18123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1813e5c487bfSMatthew G. Knepley }
1814e5c487bfSMatthew G. Knepley 
1815d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1816d71ae5a4SJacob Faibussowitsch {
1817e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1818e412dcbdSMatthew G. Knepley   DM           cdm;
1819e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1820e412dcbdSMatthew G. Knepley   Vec          coordinates;
1821c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1822e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1823c5aedaa3SMatthew G. Knepley   PetscBool    isnull, drawAffine;
1824c5aedaa3SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv;
1825e412dcbdSMatthew G. Knepley 
1826e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
18279566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
182863a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
1829c5aedaa3SMatthew G. Knepley   PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree));
1830c5aedaa3SMatthew G. Knepley   drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE;
1831c5aedaa3SMatthew G. Knepley   edgeDiv    = cDegree + 1;
18329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
18339566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
18349566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
18359566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
18369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
18379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1839e412dcbdSMatthew G. Knepley 
18409566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
18419566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
18423ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
18439566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1844e412dcbdSMatthew G. Knepley 
1845c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
18469566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
18479566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1848e412dcbdSMatthew G. Knepley 
1849cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1850cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1851c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1852ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1853c9c77995SMatthew G. Knepley     PetscBool          isDG;
1854cf3064d3SMatthew G. Knepley 
1855c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
18561baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
18571baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1858c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1859cf3064d3SMatthew G. Knepley   }
18609566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
18619566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
18629566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
18639566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
18643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1865e412dcbdSMatthew G. Knepley }
1866e412dcbdSMatthew G. Knepley 
1867e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm)
1868e44f6aebSMatthew G. Knepley {
1869e44f6aebSMatthew G. Knepley   DM           odm = dm, rdm = dm, cdm;
1870e44f6aebSMatthew G. Knepley   PetscFE      fe;
1871e44f6aebSMatthew G. Knepley   PetscSpace   sp;
1872e44f6aebSMatthew G. Knepley   PetscClassId id;
1873e44f6aebSMatthew G. Knepley   PetscInt     degree;
1874e44f6aebSMatthew G. Knepley   PetscBool    hoView = PETSC_TRUE;
1875e44f6aebSMatthew G. Knepley 
1876e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
1877e44f6aebSMatthew G. Knepley   PetscObjectOptionsBegin((PetscObject)dm);
1878e44f6aebSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL));
1879e44f6aebSMatthew G. Knepley   PetscOptionsEnd();
1880e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dm));
1881e44f6aebSMatthew G. Knepley   *hdm = dm;
1882e44f6aebSMatthew G. Knepley   if (!hoView) PetscFunctionReturn(PETSC_SUCCESS);
1883e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
1884e44f6aebSMatthew G. Knepley   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
1885e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1886e44f6aebSMatthew G. Knepley   if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS);
1887e44f6aebSMatthew G. Knepley   PetscCall(PetscFEGetBasisSpace(fe, &sp));
1888e44f6aebSMatthew G. Knepley   PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
1889e44f6aebSMatthew G. Knepley   for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) {
1890e44f6aebSMatthew G. Knepley     DM  cdm, rcdm;
1891e44f6aebSMatthew G. Knepley     Mat In;
1892e44f6aebSMatthew G. Knepley     Vec cl, rcl;
1893e44f6aebSMatthew G. Knepley 
1894e44f6aebSMatthew G. Knepley     PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm));
1895c5aedaa3SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL));
1896e44f6aebSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates"));
1897e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(odm, &cdm));
1898e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(rdm, &rcdm));
1899e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(odm, &cl));
1900e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(rdm, &rcl));
1901e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoarseDM(rcdm, cdm));
1902e44f6aebSMatthew G. Knepley     PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL));
1903e44f6aebSMatthew G. Knepley     PetscCall(MatMult(In, cl, rcl));
1904e44f6aebSMatthew G. Knepley     PetscCall(MatDestroy(&In));
1905e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(rdm, rcl));
1906e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&odm));
1907e44f6aebSMatthew G. Knepley     odm = rdm;
1908e44f6aebSMatthew G. Knepley   }
1909e44f6aebSMatthew G. Knepley   *hdm = rdm;
1910e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1911e44f6aebSMatthew G. Knepley }
1912e44f6aebSMatthew G. Knepley 
19131e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19141e50132fSMatthew G. Knepley   #include <exodusII.h>
19156823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
19161e50132fSMatthew G. Knepley #endif
19171e50132fSMatthew G. Knepley 
1918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1919d71ae5a4SJacob Faibussowitsch {
19205f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1921002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1922552f7358SJed Brown 
1923552f7358SJed Brown   PetscFunctionBegin;
1924552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1925552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
19289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
19309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
19319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
19325f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1933552f7358SJed Brown   if (iascii) {
19348135c375SStefano Zampini     PetscViewerFormat format;
19359566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
19361baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
19371baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1938c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1939c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
19409566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1941c6ccd67eSMatthew G. Knepley #else
1942c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1943552f7358SJed Brown #endif
1944e412dcbdSMatthew G. Knepley   } else if (isvtk) {
19459566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1946e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1947e44f6aebSMatthew G. Knepley     DM hdm;
1948e44f6aebSMatthew G. Knepley 
1949e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm));
1950e44f6aebSMatthew G. Knepley     PetscCall(DMPlexView_Draw(hdm, viewer));
1951e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&hdm));
19528135c375SStefano Zampini   } else if (isglvis) {
19539566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
19541e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19551e50132fSMatthew G. Knepley   } else if (isexodus) {
19566823f3c5SBlaise Bourdin     /*
19576823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
19586823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1959da81f932SPierre Jolivet       with ID 1, containing all cells.
19606823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
19616823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
19626823f3c5SBlaise Bourdin     */
19636823f3c5SBlaise Bourdin     PetscInt numCS;
19649566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
19656823f3c5SBlaise Bourdin     if (!numCS) {
19661e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
19679566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
19689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
19699566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
19706823f3c5SBlaise Bourdin     }
19719566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
19721e50132fSMatthew G. Knepley #endif
19735f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
19745f34f2dcSJed Brown   } else if (iscgns) {
19755f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
19765f34f2dcSJed Brown #endif
19771baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1978cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
19799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1980cb3ba0daSMatthew G. Knepley   if (flg) {
1981cb3ba0daSMatthew G. Knepley     Vec ranks;
19829566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
19839566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
19849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1985cb3ba0daSMatthew G. Knepley   }
1986002a2709SMatthew G. Knepley   /* Optionally view a label */
19879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1988002a2709SMatthew G. Knepley   if (flg) {
1989002a2709SMatthew G. Knepley     DMLabel label;
1990002a2709SMatthew G. Knepley     Vec     val;
1991002a2709SMatthew G. Knepley 
19929566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
199328b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
19949566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
19959566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
19969566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1997002a2709SMatthew G. Knepley   }
19983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1999552f7358SJed Brown }
2000552f7358SJed Brown 
20017f96f51bSksagiyam /*@
2002a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
20037f96f51bSksagiyam 
200420f4b53cSBarry Smith   Collective
20057f96f51bSksagiyam 
20067f96f51bSksagiyam   Input Parameters:
2007a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
2008a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
20097f96f51bSksagiyam 
20107f96f51bSksagiyam   Level: advanced
20117f96f51bSksagiyam 
20121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
20137f96f51bSksagiyam @*/
2014d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
2015d71ae5a4SJacob Faibussowitsch {
20167f96f51bSksagiyam   PetscBool ishdf5;
20177f96f51bSksagiyam 
20187f96f51bSksagiyam   PetscFunctionBegin;
20197f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20207f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
20237f96f51bSksagiyam   if (ishdf5) {
20247f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
20257f96f51bSksagiyam     PetscViewerFormat format;
20269566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20277f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20287f96f51bSksagiyam       IS globalPointNumbering;
20297f96f51bSksagiyam 
20309566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
20319566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
20329566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
203398921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
20347f96f51bSksagiyam #else
20357f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20367f96f51bSksagiyam #endif
20377f96f51bSksagiyam   }
20389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
20393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20407f96f51bSksagiyam }
20417f96f51bSksagiyam 
204277b8e257Sksagiyam /*@
2043a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
204477b8e257Sksagiyam 
204520f4b53cSBarry Smith   Collective
204677b8e257Sksagiyam 
204777b8e257Sksagiyam   Input Parameters:
2048a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
2049a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
205077b8e257Sksagiyam 
205177b8e257Sksagiyam   Level: advanced
205277b8e257Sksagiyam 
20531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
205477b8e257Sksagiyam @*/
2055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
2056d71ae5a4SJacob Faibussowitsch {
205777b8e257Sksagiyam   PetscBool ishdf5;
205877b8e257Sksagiyam 
205977b8e257Sksagiyam   PetscFunctionBegin;
206077b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
206177b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
206477b8e257Sksagiyam   if (ishdf5) {
206577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
206677b8e257Sksagiyam     PetscViewerFormat format;
20679566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
206877b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20699566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
2070fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
207177b8e257Sksagiyam #else
207277b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
207377b8e257Sksagiyam #endif
207477b8e257Sksagiyam   }
20759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
20763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207777b8e257Sksagiyam }
207877b8e257Sksagiyam 
2079bd6565f1Sksagiyam /*@
2080a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
2081bd6565f1Sksagiyam 
208220f4b53cSBarry Smith   Collective
2083bd6565f1Sksagiyam 
2084bd6565f1Sksagiyam   Input Parameters:
2085a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
2086a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
2087bd6565f1Sksagiyam 
2088bd6565f1Sksagiyam   Level: advanced
2089bd6565f1Sksagiyam 
20901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
2091bd6565f1Sksagiyam @*/
2092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
2093d71ae5a4SJacob Faibussowitsch {
2094bd6565f1Sksagiyam   PetscBool ishdf5;
2095bd6565f1Sksagiyam 
2096bd6565f1Sksagiyam   PetscFunctionBegin;
2097bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2098bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
2101bd6565f1Sksagiyam   if (ishdf5) {
2102bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
2103bd6565f1Sksagiyam     IS                globalPointNumbering;
2104bd6565f1Sksagiyam     PetscViewerFormat format;
2105bd6565f1Sksagiyam 
21069566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2107bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21089566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
21099566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
21109566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
211198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2112bd6565f1Sksagiyam #else
2113bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2114bd6565f1Sksagiyam #endif
2115bd6565f1Sksagiyam   }
21169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
21173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2118bd6565f1Sksagiyam }
2119bd6565f1Sksagiyam 
2120021affd3Sksagiyam /*@
2121a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
2122021affd3Sksagiyam 
212320f4b53cSBarry Smith   Collective
2124021affd3Sksagiyam 
2125021affd3Sksagiyam   Input Parameters:
2126a1cb98faSBarry Smith + dm        - The `DM` that contains the topology on which the section to be saved is defined
2127a1cb98faSBarry Smith . viewer    - The `PetscViewer` for saving
21280318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL`
2129021affd3Sksagiyam 
2130021affd3Sksagiyam   Level: advanced
2131021affd3Sksagiyam 
2132021affd3Sksagiyam   Notes:
2133420bcc1bSBarry 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.
2134021affd3Sksagiyam 
21350318f8a0SStefano 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.
2136021affd3Sksagiyam 
21371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
2138021affd3Sksagiyam @*/
2139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
2140d71ae5a4SJacob Faibussowitsch {
2141021affd3Sksagiyam   PetscBool ishdf5;
2142021affd3Sksagiyam 
2143021affd3Sksagiyam   PetscFunctionBegin;
2144021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2145021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21460318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2147021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
2150021affd3Sksagiyam   if (ishdf5) {
2151021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
21529566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
2153021affd3Sksagiyam #else
2154021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2155021affd3Sksagiyam #endif
2156021affd3Sksagiyam   }
21579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
21583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2159021affd3Sksagiyam }
2160021affd3Sksagiyam 
21613e97647fSksagiyam /*@
21623e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
21633e97647fSksagiyam 
216420f4b53cSBarry Smith   Collective
21653e97647fSksagiyam 
21663e97647fSksagiyam   Input Parameters:
2167a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2168a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
21690318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
21703e97647fSksagiyam - vec       - The global vector to be saved
21713e97647fSksagiyam 
21723e97647fSksagiyam   Level: advanced
21733e97647fSksagiyam 
21743e97647fSksagiyam   Notes:
21750318f8a0SStefano 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.
21763e97647fSksagiyam 
217760225df5SJacob Faibussowitsch   Calling sequence:
2178a1cb98faSBarry Smith .vb
2179a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2180a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2181a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2182a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2183a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2184a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2185a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2186a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2187a1cb98faSBarry Smith        PetscSectionSetUp(section);
2188a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2189a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2190a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2191a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2192a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2193a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2194a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2195a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2196a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2197a1cb98faSBarry Smith        DMDestroy(&dm);
2198a1cb98faSBarry Smith .ve
21993e97647fSksagiyam 
22001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22013e97647fSksagiyam @*/
2202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2203d71ae5a4SJacob Faibussowitsch {
22043e97647fSksagiyam   PetscBool ishdf5;
22053e97647fSksagiyam 
22063e97647fSksagiyam   PetscFunctionBegin;
22073e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22083e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22090318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22103e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22113e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22123e97647fSksagiyam   /* Check consistency */
22133e97647fSksagiyam   {
22143e97647fSksagiyam     PetscSection section;
22153e97647fSksagiyam     PetscBool    includesConstraints;
22163e97647fSksagiyam     PetscInt     m, m1;
22173e97647fSksagiyam 
22189566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22199566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
22209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22219566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22229566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
222363a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
22243e97647fSksagiyam   }
22259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22273e97647fSksagiyam   if (ishdf5) {
22283e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
22299566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
22303e97647fSksagiyam #else
22313e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22323e97647fSksagiyam #endif
22333e97647fSksagiyam   }
22349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22363e97647fSksagiyam }
22373e97647fSksagiyam 
22383e97647fSksagiyam /*@
22393e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
22403e97647fSksagiyam 
224120f4b53cSBarry Smith   Collective
22423e97647fSksagiyam 
22433e97647fSksagiyam   Input Parameters:
2244a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2245a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
22460318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL`
22473e97647fSksagiyam - vec       - The local vector to be saved
22483e97647fSksagiyam 
22493e97647fSksagiyam   Level: advanced
22503e97647fSksagiyam 
2251a1cb98faSBarry Smith   Note:
22520318f8a0SStefano 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.
22533e97647fSksagiyam 
225460225df5SJacob Faibussowitsch   Calling sequence:
2255a1cb98faSBarry Smith .vb
2256a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2257a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2258a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2259a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2260a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2261a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2262a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2263a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2264a1cb98faSBarry Smith        PetscSectionSetUp(section);
2265a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2266a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2267a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2268a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2269a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2270a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2271a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2272a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2273a1cb98faSBarry Smith        DMDestroy(&dm);
2274a1cb98faSBarry Smith .ve
22753e97647fSksagiyam 
22761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22773e97647fSksagiyam @*/
2278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2279d71ae5a4SJacob Faibussowitsch {
22803e97647fSksagiyam   PetscBool ishdf5;
22813e97647fSksagiyam 
22823e97647fSksagiyam   PetscFunctionBegin;
22833e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22843e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22850318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22863e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22873e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22883e97647fSksagiyam   /* Check consistency */
22893e97647fSksagiyam   {
22903e97647fSksagiyam     PetscSection section;
22913e97647fSksagiyam     PetscBool    includesConstraints;
22923e97647fSksagiyam     PetscInt     m, m1;
22933e97647fSksagiyam 
22949566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22959566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
22969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22979566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22989566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
229963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
23003e97647fSksagiyam   }
23019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23033e97647fSksagiyam   if (ishdf5) {
23043e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
23059566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
23063e97647fSksagiyam #else
23073e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23083e97647fSksagiyam #endif
23093e97647fSksagiyam   }
23109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23123e97647fSksagiyam }
23133e97647fSksagiyam 
2314d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2315d71ae5a4SJacob Faibussowitsch {
2316d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
23172c40f234SMatthew G. Knepley 
23182c40f234SMatthew G. Knepley   PetscFunctionBegin;
23192c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23202c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2322d4f5a9a0SVaclav Hapla   if (ishdf5) {
23232c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
23249c48423bSVaclav Hapla     PetscViewerFormat format;
23259566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23269c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
23279566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2328509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23299566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
233098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
23313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23322c40f234SMatthew G. Knepley #else
23332c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2334552f7358SJed Brown #endif
233598921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2336552f7358SJed Brown }
2337552f7358SJed Brown 
2338ea8e1828Sksagiyam /*@
2339a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2340ea8e1828Sksagiyam 
234120f4b53cSBarry Smith   Collective
2342ea8e1828Sksagiyam 
2343ea8e1828Sksagiyam   Input Parameters:
2344a1cb98faSBarry Smith + dm     - The `DM` into which the topology is loaded
2345a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology
2346ea8e1828Sksagiyam 
23472fe279fdSBarry Smith   Output Parameter:
234820f4b53cSBarry 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
2349dec9e869Sksagiyam 
2350ea8e1828Sksagiyam   Level: advanced
2351ea8e1828Sksagiyam 
23521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2353a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2354ea8e1828Sksagiyam @*/
2355d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2356d71ae5a4SJacob Faibussowitsch {
2357ea8e1828Sksagiyam   PetscBool ishdf5;
2358ea8e1828Sksagiyam 
2359ea8e1828Sksagiyam   PetscFunctionBegin;
2360ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2361ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23624f572ea9SToby Isaac   if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3);
23639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2365ea8e1828Sksagiyam   if (ishdf5) {
2366ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2367ea8e1828Sksagiyam     PetscViewerFormat format;
23689566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2369ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23709566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
237198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2372ea8e1828Sksagiyam #else
2373ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2374ea8e1828Sksagiyam #endif
2375ea8e1828Sksagiyam   }
23769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
23773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2378ea8e1828Sksagiyam }
2379ea8e1828Sksagiyam 
23803e701f1cSksagiyam /*@
2381a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
23823e701f1cSksagiyam 
238320f4b53cSBarry Smith   Collective
23843e701f1cSksagiyam 
23853e701f1cSksagiyam   Input Parameters:
2386a1cb98faSBarry Smith + dm                   - The `DM` into which the coordinates are loaded
2387a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved coordinates
2388a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
23893e701f1cSksagiyam 
23903e701f1cSksagiyam   Level: advanced
23913e701f1cSksagiyam 
23921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2393a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
23943e701f1cSksagiyam @*/
2395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2396d71ae5a4SJacob Faibussowitsch {
23973e701f1cSksagiyam   PetscBool ishdf5;
23983e701f1cSksagiyam 
23993e701f1cSksagiyam   PetscFunctionBegin;
24003e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24013e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2402c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24053e701f1cSksagiyam   if (ishdf5) {
24063e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
24073e701f1cSksagiyam     PetscViewerFormat format;
24089566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
24093e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24109566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
241198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
24123e701f1cSksagiyam #else
24133e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24143e701f1cSksagiyam #endif
24153e701f1cSksagiyam   }
24169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24183e701f1cSksagiyam }
24193e701f1cSksagiyam 
2420b08ad5deSksagiyam /*@
2421a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2422b08ad5deSksagiyam 
242320f4b53cSBarry Smith   Collective
2424b08ad5deSksagiyam 
2425b08ad5deSksagiyam   Input Parameters:
2426a1cb98faSBarry Smith + dm                   - The `DM` into which the labels are loaded
2427a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved labels
242820f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2429b08ad5deSksagiyam 
2430b08ad5deSksagiyam   Level: advanced
2431b08ad5deSksagiyam 
2432a1cb98faSBarry Smith   Note:
2433dc9a610eSPierre Jolivet   The `PetscSF` argument must not be `NULL` if the `DM` is distributed, otherwise an error occurs.
2434e6368b79SVaclav Hapla 
24351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2436a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2437b08ad5deSksagiyam @*/
2438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2439d71ae5a4SJacob Faibussowitsch {
2440b08ad5deSksagiyam   PetscBool ishdf5;
2441b08ad5deSksagiyam 
2442b08ad5deSksagiyam   PetscFunctionBegin;
2443b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2444b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2445e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2448b08ad5deSksagiyam   if (ishdf5) {
2449b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2450b08ad5deSksagiyam     PetscViewerFormat format;
2451b08ad5deSksagiyam 
24529566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2453b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24549566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
245598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2456b08ad5deSksagiyam #else
2457b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2458b08ad5deSksagiyam #endif
2459b08ad5deSksagiyam   }
24609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
24613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2462b08ad5deSksagiyam }
2463b08ad5deSksagiyam 
2464f84dd6b4Sksagiyam /*@
2465a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2466f84dd6b4Sksagiyam 
246720f4b53cSBarry Smith   Collective
2468f84dd6b4Sksagiyam 
2469f84dd6b4Sksagiyam   Input Parameters:
2470a1cb98faSBarry Smith + dm                   - The `DM` that represents the topology
2471a1cb98faSBarry Smith . viewer               - The `PetscViewer` that represents the on-disk section (sectionA)
24720318f8a0SStefano Zampini . sectiondm            - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL`
2473a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2474f84dd6b4Sksagiyam 
2475a4e35b19SJacob Faibussowitsch   Output Parameters:
247620f4b53cSBarry 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)
247720f4b53cSBarry 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)
2478f84dd6b4Sksagiyam 
2479f84dd6b4Sksagiyam   Level: advanced
2480f84dd6b4Sksagiyam 
2481f84dd6b4Sksagiyam   Notes:
248220f4b53cSBarry 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.
2483f84dd6b4Sksagiyam 
24840318f8a0SStefano 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.
2485f84dd6b4Sksagiyam 
248620f4b53cSBarry 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.
2487f84dd6b4Sksagiyam 
2488f84dd6b4Sksagiyam   Example using 2 processes:
2489a1cb98faSBarry Smith .vb
2490a1cb98faSBarry Smith   NX (number of points on dm): 4
2491a1cb98faSBarry Smith   sectionA                   : the on-disk section
2492a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2493a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2494a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2495a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2496f84dd6b4Sksagiyam 
2497a1cb98faSBarry Smith                                      rank 0    rank 1
2498a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2499a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2500a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2501a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2502a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2503a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2504a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2505a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2506a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2507a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2508a1cb98faSBarry Smith .ve
2509a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2510a1cb98faSBarry Smith 
25111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2512f84dd6b4Sksagiyam @*/
2513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2514d71ae5a4SJacob Faibussowitsch {
2515f84dd6b4Sksagiyam   PetscBool ishdf5;
2516f84dd6b4Sksagiyam 
2517f84dd6b4Sksagiyam   PetscFunctionBegin;
2518f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2519f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25200318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2521f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2522f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
25234f572ea9SToby Isaac   if (globalDofSF) PetscAssertPointer(globalDofSF, 5);
25244f572ea9SToby Isaac   if (localDofSF) PetscAssertPointer(localDofSF, 6);
25259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2527f84dd6b4Sksagiyam   if (ishdf5) {
2528f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
25299566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2530f84dd6b4Sksagiyam #else
2531f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2532f84dd6b4Sksagiyam #endif
2533f84dd6b4Sksagiyam   }
25349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
25353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2536f84dd6b4Sksagiyam }
2537f84dd6b4Sksagiyam 
25388be3dfe1Sksagiyam /*@
25398be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
25408be3dfe1Sksagiyam 
254120f4b53cSBarry Smith   Collective
25428be3dfe1Sksagiyam 
25438be3dfe1Sksagiyam   Input Parameters:
2544a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2545a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
25460318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
2547a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
25488be3dfe1Sksagiyam - vec       - The global vector to set values of
25498be3dfe1Sksagiyam 
25508be3dfe1Sksagiyam   Level: advanced
25518be3dfe1Sksagiyam 
25528be3dfe1Sksagiyam   Notes:
25530318f8a0SStefano 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.
25548be3dfe1Sksagiyam 
255560225df5SJacob Faibussowitsch   Calling sequence:
2556a1cb98faSBarry Smith .vb
2557a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2558a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2559a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2560a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2561a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2562a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2563a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2564a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2565a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2566a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2567a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2568a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2569a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2570a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2571a1cb98faSBarry Smith        DMDestroy(&dm);
2572a1cb98faSBarry Smith .ve
25738be3dfe1Sksagiyam 
25741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2575a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
25768be3dfe1Sksagiyam @*/
2577d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2578d71ae5a4SJacob Faibussowitsch {
25798be3dfe1Sksagiyam   PetscBool ishdf5;
25808be3dfe1Sksagiyam 
25818be3dfe1Sksagiyam   PetscFunctionBegin;
25828be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25838be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25840318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
25858be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
25868be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
25878be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
25888be3dfe1Sksagiyam   /* Check consistency */
25898be3dfe1Sksagiyam   {
25908be3dfe1Sksagiyam     PetscSection section;
25918be3dfe1Sksagiyam     PetscBool    includesConstraints;
25928be3dfe1Sksagiyam     PetscInt     m, m1;
25938be3dfe1Sksagiyam 
25949566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25959566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
25969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25979566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25989566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
259963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
26008be3dfe1Sksagiyam   }
26019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26038be3dfe1Sksagiyam   if (ishdf5) {
26048be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26059566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26068be3dfe1Sksagiyam #else
26078be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26088be3dfe1Sksagiyam #endif
26098be3dfe1Sksagiyam   }
26109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26128be3dfe1Sksagiyam }
26138be3dfe1Sksagiyam 
26148be3dfe1Sksagiyam /*@
26158be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
26168be3dfe1Sksagiyam 
261720f4b53cSBarry Smith   Collective
26188be3dfe1Sksagiyam 
26198be3dfe1Sksagiyam   Input Parameters:
2620a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2621a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
26220318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL`
2623a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
26248be3dfe1Sksagiyam - vec       - The local vector to set values of
26258be3dfe1Sksagiyam 
26268be3dfe1Sksagiyam   Level: advanced
26278be3dfe1Sksagiyam 
26288be3dfe1Sksagiyam   Notes:
26290318f8a0SStefano 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.
26308be3dfe1Sksagiyam 
263160225df5SJacob Faibussowitsch   Calling sequence:
2632a1cb98faSBarry Smith .vb
2633a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2634a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2635a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2636a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2637a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2638a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2639a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2640a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2641a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2642a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2643a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2644a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2645a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2646a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2647a1cb98faSBarry Smith        DMDestroy(&dm);
2648a1cb98faSBarry Smith .ve
26498be3dfe1Sksagiyam 
26501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2651a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
26528be3dfe1Sksagiyam @*/
2653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2654d71ae5a4SJacob Faibussowitsch {
26558be3dfe1Sksagiyam   PetscBool ishdf5;
26568be3dfe1Sksagiyam 
26578be3dfe1Sksagiyam   PetscFunctionBegin;
26588be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26598be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
26600318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
26618be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
26628be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
26638be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
26648be3dfe1Sksagiyam   /* Check consistency */
26658be3dfe1Sksagiyam   {
26668be3dfe1Sksagiyam     PetscSection section;
26678be3dfe1Sksagiyam     PetscBool    includesConstraints;
26688be3dfe1Sksagiyam     PetscInt     m, m1;
26698be3dfe1Sksagiyam 
26709566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
26719566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
26729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
26739566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
26749566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
267563a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
26768be3dfe1Sksagiyam   }
26779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26789566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26798be3dfe1Sksagiyam   if (ishdf5) {
26808be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26819566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26828be3dfe1Sksagiyam #else
26838be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26848be3dfe1Sksagiyam #endif
26858be3dfe1Sksagiyam   }
26869566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26888be3dfe1Sksagiyam }
26898be3dfe1Sksagiyam 
2690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2691d71ae5a4SJacob Faibussowitsch {
2692552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2693552f7358SJed Brown 
2694552f7358SJed Brown   PetscFunctionBegin;
26959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
26969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
26979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
26989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
26996c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL));
27002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
27012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
27022e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
27032e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
27046bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
27056bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2706adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL));
2707adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL));
2708adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL));
2709adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL));
2710c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2711c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
2712d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL));
2713d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL));
27145f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
27153ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
27169566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
27179566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
27189566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
27199566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
27209566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
27219566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
272221027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
27239f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
27249566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
27259566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
27269566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
27271d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
27289566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
27299566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
27309566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
27319566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
27329566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
27334e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
27346725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
27356725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
27369566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
27379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
27389566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
27399566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
27409566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
27419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
27429566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
27439566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
27449566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
27459566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
27469566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2747552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
27489566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
27493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2750552f7358SJed Brown }
2751552f7358SJed Brown 
2752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2753d71ae5a4SJacob Faibussowitsch {
2754d02c7345SMatthew G. Knepley   PetscSection           sectionGlobal, sectionLocal;
2755acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
27569fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2757837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2758b412c318SBarry Smith   MatType                mtype;
27591428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2760552f7358SJed Brown 
2761552f7358SJed Brown   PetscFunctionBegin;
27629566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2763b412c318SBarry Smith   mtype = dm->mattype;
2764d02c7345SMatthew G. Knepley   PetscCall(DMGetLocalSection(dm, &sectionLocal));
27659566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
27669566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
27679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
27689fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
27699566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
27709566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
27719566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
27729566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
27739566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2774acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
27759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
27769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
27779566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
27789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
27799566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
27809566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
27819566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
27829566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2783552f7358SJed Brown   if (!isShell) {
2784837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
27859fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2786863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2787552f7358SJed Brown 
27889566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
27899fca9976SJed Brown 
27909fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
27919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2792863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2793e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2794863027abSJed Brown       switch (dm->blocking_type) {
27950e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
27969fca9976SJed Brown         PetscInt bdof, offset;
2797a9d99c84SMatthew G. Knepley 
27989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
27999fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
28009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
2801*32b27637SMatthew G. Knepley         if (dof > 0) {
2802d02c7345SMatthew G. Knepley           for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof;
2803d02c7345SMatthew G. Knepley           // Signal block concatenation
2804d02c7345SMatthew G. Knepley           if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof);
2805*32b27637SMatthew G. Knepley         }
28061d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
28071d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
28081d17a0a3SMatthew G. Knepley         if (dof) {
28099371c9d4SSatish Balay           if (bs < 0) {
28109371c9d4SSatish Balay             bs = bdof;
28119371c9d4SSatish Balay           } else if (bs != bdof) {
28129371c9d4SSatish Balay             bs = 1;
28139371c9d4SSatish Balay           }
2814552f7358SJed Brown         }
2815863027abSJed Brown       } break;
2816863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2817863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2818863027abSJed Brown           PetscInt num_comp, bdof, offset;
2819863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2820863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2821863027abSJed Brown           if (dof < 0) continue;
2822863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2823863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2824863027abSJed 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);
2825863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2826863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2827863027abSJed Brown           // Handle possibly constant block size (unlikely)
2828863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2829863027abSJed Brown           if (dof) {
2830863027abSJed Brown             if (bs < 0) {
2831863027abSJed Brown               bs = bdof;
2832863027abSJed Brown             } else if (bs != bdof) {
2833863027abSJed Brown               bs = 1;
2834863027abSJed Brown             }
2835863027abSJed Brown           }
2836863027abSJed Brown         }
2837863027abSJed Brown       } break;
2838863027abSJed Brown       }
28392a28c762SMatthew G Knepley     }
28402a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2841e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2842e432b41dSStefano Zampini     bsLocal[1] = bs;
28439566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2844e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2845e432b41dSStefano Zampini     else bs = bsMinMax[0];
28466fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
28479566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
28480682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
28499566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
28509566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
28510682b8bbSJed Brown     } else {
28529566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
28539566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
28549566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2855552f7358SJed Brown     }
2856*32b27637SMatthew G. Knepley     if (pblocks) { // Consolidate blocks
28579fca9976SJed Brown       PetscInt nblocks = 0;
2858*32b27637SMatthew G. Knepley       pblocks[0]       = PetscAbs(pblocks[0]);
28599fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
28609fca9976SJed Brown         if (pblocks[i] == 0) continue;
2861d02c7345SMatthew G. Knepley         // Negative block size indicates the blocks should be concatenated
2862d02c7345SMatthew G. Knepley         if (pblocks[i] < 0) {
2863d02c7345SMatthew G. Knepley           pblocks[i] = -pblocks[i];
2864d02c7345SMatthew G. Knepley           pblocks[nblocks - 1] += pblocks[i];
2865d02c7345SMatthew G. Knepley         } else {
28669fca9976SJed Brown           pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2867d02c7345SMatthew G. Knepley         }
2868ad540459SPierre 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]);
28699fca9976SJed Brown       }
28709fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
28719fca9976SJed Brown     }
28729fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2873aa0f6e3cSJed Brown   }
28749566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
28753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2876552f7358SJed Brown }
2877552f7358SJed Brown 
28787cd05799SMatthew G. Knepley /*@
2879a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2880be36d101SStefano Zampini 
2881a1cb98faSBarry Smith   Not Collective
2882be36d101SStefano Zampini 
2883be36d101SStefano Zampini   Input Parameter:
288460225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2885be36d101SStefano Zampini 
28862fe279fdSBarry Smith   Output Parameter:
2887be36d101SStefano Zampini . subsection - The subdomain section
2888be36d101SStefano Zampini 
2889be36d101SStefano Zampini   Level: developer
2890be36d101SStefano Zampini 
28911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
28927cd05799SMatthew G. Knepley @*/
2893d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2894d71ae5a4SJacob Faibussowitsch {
2895be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2896be36d101SStefano Zampini 
2897be36d101SStefano Zampini   PetscFunctionBegin;
2898be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2899be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2900be36d101SStefano Zampini     PetscSection section;
2901be36d101SStefano Zampini     PetscSF      sf;
2902be36d101SStefano Zampini 
29039566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
29049566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
2905eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
29069566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2907be36d101SStefano Zampini   }
2908be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
29093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2910be36d101SStefano Zampini }
2911be36d101SStefano Zampini 
2912552f7358SJed Brown /*@
291320f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2914552f7358SJed Brown 
2915a1cb98faSBarry Smith   Not Collective
2916552f7358SJed Brown 
2917552f7358SJed Brown   Input Parameter:
291860225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2919552f7358SJed Brown 
2920552f7358SJed Brown   Output Parameters:
2921552f7358SJed Brown + pStart - The first mesh point
2922552f7358SJed Brown - pEnd   - The upper bound for mesh points
2923552f7358SJed Brown 
2924552f7358SJed Brown   Level: beginner
2925552f7358SJed Brown 
29261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2927552f7358SJed Brown @*/
2928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2929d71ae5a4SJacob Faibussowitsch {
2930552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2931552f7358SJed Brown 
2932552f7358SJed Brown   PetscFunctionBegin;
2933552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29349f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
29359f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
29363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2937552f7358SJed Brown }
2938552f7358SJed Brown 
2939552f7358SJed Brown /*@
294020f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2941552f7358SJed Brown 
2942a1cb98faSBarry Smith   Not Collective
2943552f7358SJed Brown 
2944552f7358SJed Brown   Input Parameters:
294560225df5SJacob Faibussowitsch + dm     - The `DMPLEX`
2946552f7358SJed Brown . pStart - The first mesh point
2947552f7358SJed Brown - pEnd   - The upper bound for mesh points
2948552f7358SJed Brown 
2949552f7358SJed Brown   Level: beginner
2950552f7358SJed Brown 
29511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2952552f7358SJed Brown @*/
2953d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2954d71ae5a4SJacob Faibussowitsch {
2955552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2956552f7358SJed Brown 
2957552f7358SJed Brown   PetscFunctionBegin;
2958552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
29609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
296121027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
29623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2963552f7358SJed Brown }
2964552f7358SJed Brown 
2965552f7358SJed Brown /*@
2966eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2967552f7358SJed Brown 
2968a1cb98faSBarry Smith   Not Collective
2969552f7358SJed Brown 
2970552f7358SJed Brown   Input Parameters:
297160225df5SJacob Faibussowitsch + dm - The `DMPLEX`
2972a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2973552f7358SJed Brown 
2974552f7358SJed Brown   Output Parameter:
297520f4b53cSBarry Smith . size - The cone size for point `p`
2976552f7358SJed Brown 
2977552f7358SJed Brown   Level: beginner
2978552f7358SJed Brown 
29791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2980552f7358SJed Brown @*/
2981d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2982d71ae5a4SJacob Faibussowitsch {
2983552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2984552f7358SJed Brown 
2985552f7358SJed Brown   PetscFunctionBegin;
2986552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29874f572ea9SToby Isaac   PetscAssertPointer(size, 3);
29889f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
29899f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
29903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2991552f7358SJed Brown }
2992552f7358SJed Brown 
2993552f7358SJed Brown /*@
2994eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2995552f7358SJed Brown 
2996a1cb98faSBarry Smith   Not Collective
2997552f7358SJed Brown 
2998552f7358SJed Brown   Input Parameters:
299960225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3000a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
300120f4b53cSBarry Smith - size - The cone size for point `p`
3002552f7358SJed Brown 
3003552f7358SJed Brown   Level: beginner
3004552f7358SJed Brown 
3005a1cb98faSBarry Smith   Note:
3006a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
3007a1cb98faSBarry Smith 
30081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
3009552f7358SJed Brown @*/
3010d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
3011d71ae5a4SJacob Faibussowitsch {
3012552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3013552f7358SJed Brown 
3014552f7358SJed Brown   PetscFunctionBegin;
3015552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30169f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
30179566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
30183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3019552f7358SJed Brown }
3020552f7358SJed Brown 
3021552f7358SJed Brown /*@C
3022eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
3023552f7358SJed Brown 
3024a1cb98faSBarry Smith   Not Collective
3025552f7358SJed Brown 
3026552f7358SJed Brown   Input Parameters:
3027a1cb98faSBarry Smith + dm - The `DMPLEX`
3028a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3029552f7358SJed Brown 
3030552f7358SJed Brown   Output Parameter:
303120f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
3032552f7358SJed Brown 
3033552f7358SJed Brown   Level: beginner
3034552f7358SJed Brown 
303560225df5SJacob Faibussowitsch   Fortran Notes:
3036a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
3037a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
30383813dfbdSMatthew G Knepley 
30391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
3040552f7358SJed Brown @*/
3041d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
3042d71ae5a4SJacob Faibussowitsch {
3043552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3044552f7358SJed Brown   PetscInt off;
3045552f7358SJed Brown 
3046552f7358SJed Brown   PetscFunctionBegin;
3047552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30484f572ea9SToby Isaac   PetscAssertPointer(cone, 3);
30499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30508e3a54c0SPierre Jolivet   *cone = PetscSafePointerPlusOffset(mesh->cones, off);
30513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3052552f7358SJed Brown }
3053552f7358SJed Brown 
30540ce7577fSVaclav Hapla /*@C
30550ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
30560ce7577fSVaclav Hapla 
3057a1cb98faSBarry Smith   Not Collective
30580ce7577fSVaclav Hapla 
30590ce7577fSVaclav Hapla   Input Parameters:
3060a1cb98faSBarry Smith + dm - The `DMPLEX`
3061a1cb98faSBarry Smith - p  - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
30620ce7577fSVaclav Hapla 
3063d8d19677SJose E. Roman   Output Parameters:
306420f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
306520f4b53cSBarry Smith - pCones        - An array of points which are on the in-edges for the point set `p`
30660ce7577fSVaclav Hapla 
30670ce7577fSVaclav Hapla   Level: intermediate
30680ce7577fSVaclav Hapla 
30691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
30700ce7577fSVaclav Hapla @*/
3071d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
3072d71ae5a4SJacob Faibussowitsch {
30730ce7577fSVaclav Hapla   PetscSection cs, newcs;
30740ce7577fSVaclav Hapla   PetscInt    *cones;
30750ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
30760ce7577fSVaclav Hapla   PetscInt     n;
30770ce7577fSVaclav Hapla 
30780ce7577fSVaclav Hapla   PetscFunctionBegin;
30799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
30809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
30819566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
30820ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
30830ce7577fSVaclav Hapla   if (pCones) {
30849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
30859566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
30860ce7577fSVaclav Hapla   }
30873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30880ce7577fSVaclav Hapla }
30890ce7577fSVaclav Hapla 
3090af9eab45SVaclav Hapla /*@
3091af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
3092d4636a37SVaclav Hapla 
3093a1cb98faSBarry Smith   Not Collective
3094d4636a37SVaclav Hapla 
3095d4636a37SVaclav Hapla   Input Parameters:
3096a1cb98faSBarry Smith + dm     - The `DMPLEX`
3097a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3098d4636a37SVaclav Hapla 
3099d4636a37SVaclav Hapla   Output Parameter:
3100af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
3101d4636a37SVaclav Hapla 
3102d4636a37SVaclav Hapla   Level: advanced
3103d4636a37SVaclav Hapla 
3104af9eab45SVaclav Hapla   Notes:
310520f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
3106af9eab45SVaclav Hapla 
3107a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
3108a1cb98faSBarry Smith 
31091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
3110a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
3111d4636a37SVaclav Hapla @*/
3112d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
3113d71ae5a4SJacob Faibussowitsch {
3114af9eab45SVaclav Hapla   IS      *expandedPointsAll;
3115af9eab45SVaclav Hapla   PetscInt depth;
3116d4636a37SVaclav Hapla 
3117d4636a37SVaclav Hapla   PetscFunctionBegin;
3118af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3119af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31204f572ea9SToby Isaac   PetscAssertPointer(expandedPoints, 3);
31219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
3122af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
31239566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
31249566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
31253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3126af9eab45SVaclav Hapla }
3127af9eab45SVaclav Hapla 
3128af9eab45SVaclav Hapla /*@
3129af9eab45SVaclav 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).
3130af9eab45SVaclav Hapla 
3131a1cb98faSBarry Smith   Not Collective
3132af9eab45SVaclav Hapla 
3133af9eab45SVaclav Hapla   Input Parameters:
3134a1cb98faSBarry Smith + dm     - The `DMPLEX`
3135a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3136af9eab45SVaclav Hapla 
3137d8d19677SJose E. Roman   Output Parameters:
3138a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3139af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
3140af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3141af9eab45SVaclav Hapla 
3142af9eab45SVaclav Hapla   Level: advanced
3143af9eab45SVaclav Hapla 
3144af9eab45SVaclav Hapla   Notes:
3145a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
3146af9eab45SVaclav Hapla 
3147a4e35b19SJacob 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.
3148af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
3149af9eab45SVaclav Hapla 
3150a4e35b19SJacob 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\:
3151a4e35b19SJacob Faibussowitsch   (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
3152a4e35b19SJacob Faibussowitsch   (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
3153af9eab45SVaclav Hapla 
31541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3155a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
3156af9eab45SVaclav Hapla @*/
3157d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3158d71ae5a4SJacob Faibussowitsch {
3159af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
3160af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
3161af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
3162af9eab45SVaclav Hapla   IS             *expandedPoints_;
3163af9eab45SVaclav Hapla   PetscSection   *sections_;
3164af9eab45SVaclav Hapla 
3165af9eab45SVaclav Hapla   PetscFunctionBegin;
3166af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3167af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31684f572ea9SToby Isaac   if (depth) PetscAssertPointer(depth, 3);
31694f572ea9SToby Isaac   if (expandedPoints) PetscAssertPointer(expandedPoints, 4);
31704f572ea9SToby Isaac   if (sections) PetscAssertPointer(sections, 5);
31719566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
31729566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
31739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
31749566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
31759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
3176af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
3177af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
31789566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
31799566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
3180af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
3182af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
31839566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
31849566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
3185af9eab45SVaclav Hapla       } else {
31869566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
3187af9eab45SVaclav Hapla       }
3188af9eab45SVaclav Hapla     }
31899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
31909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
31919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
3192af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
31949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
3195af9eab45SVaclav Hapla       if (cn > 1) {
31969566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
31979566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3198af9eab45SVaclav Hapla       } else {
3199af9eab45SVaclav Hapla         newarr[co] = arr[i];
3200af9eab45SVaclav Hapla       }
3201af9eab45SVaclav Hapla     }
32029566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3203af9eab45SVaclav Hapla     arr = newarr;
3204af9eab45SVaclav Hapla     n   = newn;
3205af9eab45SVaclav Hapla   }
32069566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3207af9eab45SVaclav Hapla   *depth = depth_;
3208af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3209af9eab45SVaclav Hapla   else {
32109566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
32119566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3212af9eab45SVaclav Hapla   }
3213af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3214af9eab45SVaclav Hapla   else {
32159566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
32169566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3217af9eab45SVaclav Hapla   }
32183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3219af9eab45SVaclav Hapla }
3220af9eab45SVaclav Hapla 
3221af9eab45SVaclav Hapla /*@
3222a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3223af9eab45SVaclav Hapla 
3224a1cb98faSBarry Smith   Not Collective
3225af9eab45SVaclav Hapla 
3226af9eab45SVaclav Hapla   Input Parameters:
3227a1cb98faSBarry Smith + dm     - The `DMPLEX`
3228a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3229af9eab45SVaclav Hapla 
3230d8d19677SJose E. Roman   Output Parameters:
3231a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3232af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3233af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3234af9eab45SVaclav Hapla 
3235af9eab45SVaclav Hapla   Level: advanced
3236af9eab45SVaclav Hapla 
3237a1cb98faSBarry Smith   Note:
3238a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3239af9eab45SVaclav Hapla 
32401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3241a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3242af9eab45SVaclav Hapla @*/
3243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3244d71ae5a4SJacob Faibussowitsch {
3245af9eab45SVaclav Hapla   PetscInt d, depth_;
3246af9eab45SVaclav Hapla 
3247af9eab45SVaclav Hapla   PetscFunctionBegin;
32489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
32491dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3250af9eab45SVaclav Hapla   if (depth) *depth = 0;
3251af9eab45SVaclav Hapla   if (expandedPoints) {
32529566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
32539566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3254af9eab45SVaclav Hapla   }
3255af9eab45SVaclav Hapla   if (sections) {
32569566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
32579566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3258af9eab45SVaclav Hapla   }
32593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3260d4636a37SVaclav Hapla }
3261d4636a37SVaclav Hapla 
3262552f7358SJed Brown /*@
326392371b87SBarry 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
3264552f7358SJed Brown 
3265a1cb98faSBarry Smith   Not Collective
3266552f7358SJed Brown 
3267552f7358SJed Brown   Input Parameters:
326860225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3269a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
327020f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3271552f7358SJed Brown 
3272552f7358SJed Brown   Level: beginner
3273552f7358SJed Brown 
3274a1cb98faSBarry Smith   Note:
3275a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3276a1cb98faSBarry Smith 
32771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3278552f7358SJed Brown @*/
3279d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3280d71ae5a4SJacob Faibussowitsch {
3281552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3282552f7358SJed Brown   PetscInt dof, off, c;
3283552f7358SJed Brown 
3284552f7358SJed Brown   PetscFunctionBegin;
3285552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32874f572ea9SToby Isaac   if (dof) PetscAssertPointer(cone, 3);
32889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3289db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3290db485b19SStefano Zampini     PetscInt pStart, pEnd;
3291db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
329263a3b9bcSJacob 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);
3293552f7358SJed Brown     for (c = 0; c < dof; ++c) {
329463a3b9bcSJacob 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);
3295552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3296552f7358SJed Brown     }
3297db485b19SStefano Zampini   } else {
3298db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3299db485b19SStefano Zampini   }
33003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3301552f7358SJed Brown }
3302552f7358SJed Brown 
3303552f7358SJed Brown /*@C
3304eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3305552f7358SJed Brown 
3306a1cb98faSBarry Smith   Not Collective
3307552f7358SJed Brown 
3308552f7358SJed Brown   Input Parameters:
330960225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3310a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3311552f7358SJed Brown 
3312552f7358SJed Brown   Output Parameter:
331320f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3314b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3315552f7358SJed Brown 
3316552f7358SJed Brown   Level: beginner
3317552f7358SJed Brown 
3318a1cb98faSBarry Smith   Note:
3319b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3320b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3321a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3322b5a892a1SMatthew G. Knepley   with the identity.
3323b5a892a1SMatthew G. Knepley 
332460225df5SJacob Faibussowitsch   Fortran Notes:
3325a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3326a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
33273813dfbdSMatthew G Knepley 
33281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3329552f7358SJed Brown @*/
3330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3331d71ae5a4SJacob Faibussowitsch {
3332552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3333552f7358SJed Brown   PetscInt off;
3334552f7358SJed Brown 
3335552f7358SJed Brown   PetscFunctionBegin;
3336552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3338552f7358SJed Brown     PetscInt dof;
33399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33404f572ea9SToby Isaac     if (dof) PetscAssertPointer(coneOrientation, 3);
3341552f7358SJed Brown   }
33429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33430d644c17SKarl Rupp 
3344552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
33453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3346552f7358SJed Brown }
3347552f7358SJed Brown 
3348552f7358SJed Brown /*@
3349eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3350552f7358SJed Brown 
3351a1cb98faSBarry Smith   Not Collective
3352552f7358SJed Brown 
3353552f7358SJed Brown   Input Parameters:
335460225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3355a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
3356b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3357b5a892a1SMatthew G. Knepley 
3358552f7358SJed Brown   Level: beginner
3359552f7358SJed Brown 
3360a1cb98faSBarry Smith   Notes:
3361a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3362a1cb98faSBarry Smith 
3363a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3364a1cb98faSBarry Smith 
33651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3366552f7358SJed Brown @*/
3367d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3368d71ae5a4SJacob Faibussowitsch {
3369552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3370552f7358SJed Brown   PetscInt pStart, pEnd;
3371552f7358SJed Brown   PetscInt dof, off, c;
3372552f7358SJed Brown 
3373552f7358SJed Brown   PetscFunctionBegin;
3374552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33764f572ea9SToby Isaac   if (dof) PetscAssertPointer(coneOrientation, 3);
33779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3378db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3379db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
338063a3b9bcSJacob 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);
3381552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3382552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3383552f7358SJed Brown 
33849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
33851dca8a05SBarry 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);
3386552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3387552f7358SJed Brown     }
3388db485b19SStefano Zampini   } else {
3389db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3390db485b19SStefano Zampini   }
33913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3392552f7358SJed Brown }
3393552f7358SJed Brown 
33947cd05799SMatthew G. Knepley /*@
3395eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
33967cd05799SMatthew G. Knepley 
3397a1cb98faSBarry Smith   Not Collective
33987cd05799SMatthew G. Knepley 
33997cd05799SMatthew G. Knepley   Input Parameters:
340060225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
3401a1cb98faSBarry Smith . p         - The point, which must lie in the chart set with `DMPlexSetChart()`
34027cd05799SMatthew G. Knepley . conePos   - The local index in the cone where the point should be put
34037cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
34047cd05799SMatthew G. Knepley 
34057cd05799SMatthew G. Knepley   Level: beginner
34067cd05799SMatthew G. Knepley 
34071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34087cd05799SMatthew G. Knepley @*/
3409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3410d71ae5a4SJacob Faibussowitsch {
3411552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3412552f7358SJed Brown   PetscInt pStart, pEnd;
3413552f7358SJed Brown   PetscInt dof, off;
3414552f7358SJed Brown 
3415552f7358SJed Brown   PetscFunctionBegin;
3416552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3417a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
341963a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
342063a3b9bcSJacob 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);
34219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
342263a3b9bcSJacob 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);
3423a03d55ffSStefano Zampini   }
3424a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3425552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
34263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3427552f7358SJed Brown }
3428552f7358SJed Brown 
34297cd05799SMatthew G. Knepley /*@
3430eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
34317cd05799SMatthew G. Knepley 
3432a1cb98faSBarry Smith   Not Collective
34337cd05799SMatthew G. Knepley 
34347cd05799SMatthew G. Knepley   Input Parameters:
343560225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3436a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
34377cd05799SMatthew G. Knepley . conePos         - The local index in the cone where the point should be put
34387cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
34397cd05799SMatthew G. Knepley 
34407cd05799SMatthew G. Knepley   Level: beginner
34417cd05799SMatthew G. Knepley 
3442a1cb98faSBarry Smith   Note:
3443a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3444b5a892a1SMatthew G. Knepley 
34451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34467cd05799SMatthew G. Knepley @*/
3447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3448d71ae5a4SJacob Faibussowitsch {
344977c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
345077c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
345177c88f5bSMatthew G Knepley   PetscInt dof, off;
345277c88f5bSMatthew G Knepley 
345377c88f5bSMatthew G Knepley   PetscFunctionBegin;
345477c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3455a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
345763a3b9bcSJacob 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);
34589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
345963a3b9bcSJacob 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);
3460a03d55ffSStefano Zampini   }
3461a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
346277c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
34633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346477c88f5bSMatthew G Knepley }
346577c88f5bSMatthew G Knepley 
34669f4ada15SMatthew G. Knepley /*@C
34679f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
34689f4ada15SMatthew G. Knepley 
34699f4ada15SMatthew G. Knepley   Not collective
34709f4ada15SMatthew G. Knepley 
34719f4ada15SMatthew G. Knepley   Input Parameters:
34729f4ada15SMatthew G. Knepley + dm - The DMPlex
34739f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
34749f4ada15SMatthew G. Knepley 
34759f4ada15SMatthew G. Knepley   Output Parameters:
347620f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
347720f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
34789f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
34799f4ada15SMatthew G. Knepley 
34809f4ada15SMatthew G. Knepley   Level: beginner
34819f4ada15SMatthew G. Knepley 
34829f4ada15SMatthew G. Knepley   Notes:
34839f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
34849f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
348520f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
34869f4ada15SMatthew G. Knepley   with the identity.
34879f4ada15SMatthew G. Knepley 
34889f4ada15SMatthew G. Knepley   Fortran Notes:
348920f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
349020f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
34919f4ada15SMatthew G. Knepley 
34921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
34939f4ada15SMatthew G. Knepley @*/
34949f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
34959f4ada15SMatthew G. Knepley {
34969f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
34979f4ada15SMatthew G. Knepley 
34989f4ada15SMatthew G. Knepley   PetscFunctionBegin;
34999f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35009f4ada15SMatthew G. Knepley   if (mesh->tr) {
35019f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
35029f4ada15SMatthew G. Knepley   } else {
35039f4ada15SMatthew G. Knepley     PetscInt off;
35049f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
35059f4ada15SMatthew G. Knepley       PetscInt dof;
35069f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
35079f4ada15SMatthew G. Knepley       if (dof) {
35084f572ea9SToby Isaac         if (cone) PetscAssertPointer(cone, 3);
35094f572ea9SToby Isaac         if (ornt) PetscAssertPointer(ornt, 4);
35109f4ada15SMatthew G. Knepley       }
35119f4ada15SMatthew G. Knepley     }
35129f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
35138e3a54c0SPierre Jolivet     if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off);
35148e3a54c0SPierre Jolivet     if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off);
35159f4ada15SMatthew G. Knepley   }
35163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35179f4ada15SMatthew G. Knepley }
35189f4ada15SMatthew G. Knepley 
35199f4ada15SMatthew G. Knepley /*@C
35209f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
35219f4ada15SMatthew G. Knepley 
352220f4b53cSBarry Smith   Not Collective
35239f4ada15SMatthew G. Knepley 
35249f4ada15SMatthew G. Knepley   Input Parameters:
35259f4ada15SMatthew G. Knepley + dm   - The DMPlex
352620f4b53cSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
35279f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
352820f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
35299f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
35309f4ada15SMatthew G. Knepley 
35319f4ada15SMatthew G. Knepley   Level: beginner
35329f4ada15SMatthew G. Knepley 
35339f4ada15SMatthew G. Knepley   Notes:
35349f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
35359f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
353620f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
35379f4ada15SMatthew G. Knepley   with the identity.
35389f4ada15SMatthew G. Knepley 
353960225df5SJacob Faibussowitsch   Fortran Notes:
354020f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
354120f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
35429f4ada15SMatthew G. Knepley 
35431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
35449f4ada15SMatthew G. Knepley @*/
35459f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
35469f4ada15SMatthew G. Knepley {
35479f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
35489f4ada15SMatthew G. Knepley 
35499f4ada15SMatthew G. Knepley   PetscFunctionBegin;
35509f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35519f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
35523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35539f4ada15SMatthew G. Knepley }
35549f4ada15SMatthew G. Knepley 
3555552f7358SJed Brown /*@
3556eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3557552f7358SJed Brown 
3558a1cb98faSBarry Smith   Not Collective
3559552f7358SJed Brown 
3560552f7358SJed Brown   Input Parameters:
356160225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3562a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3563552f7358SJed Brown 
3564552f7358SJed Brown   Output Parameter:
356520f4b53cSBarry Smith . size - The support size for point `p`
3566552f7358SJed Brown 
3567552f7358SJed Brown   Level: beginner
3568552f7358SJed Brown 
35691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3570552f7358SJed Brown @*/
3571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3572d71ae5a4SJacob Faibussowitsch {
3573552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3574552f7358SJed Brown 
3575552f7358SJed Brown   PetscFunctionBegin;
3576552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35774f572ea9SToby Isaac   PetscAssertPointer(size, 3);
35789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
35793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3580552f7358SJed Brown }
3581552f7358SJed Brown 
3582552f7358SJed Brown /*@
3583eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3584552f7358SJed Brown 
3585a1cb98faSBarry Smith   Not Collective
3586552f7358SJed Brown 
3587552f7358SJed Brown   Input Parameters:
358860225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3589a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
359020f4b53cSBarry Smith - size - The support size for point `p`
3591552f7358SJed Brown 
3592a1cb98faSBarry Smith   Level: beginner
3593552f7358SJed Brown 
3594552f7358SJed Brown   Note:
359520f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3596552f7358SJed Brown 
35971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3598552f7358SJed Brown @*/
3599d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3600d71ae5a4SJacob Faibussowitsch {
3601552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3602552f7358SJed Brown 
3603552f7358SJed Brown   PetscFunctionBegin;
3604552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
36063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3607552f7358SJed Brown }
3608552f7358SJed Brown 
3609552f7358SJed Brown /*@C
3610eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3611552f7358SJed Brown 
3612a1cb98faSBarry Smith   Not Collective
3613552f7358SJed Brown 
3614552f7358SJed Brown   Input Parameters:
361560225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3616a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3617552f7358SJed Brown 
3618552f7358SJed Brown   Output Parameter:
361920f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3620552f7358SJed Brown 
3621552f7358SJed Brown   Level: beginner
3622552f7358SJed Brown 
362360225df5SJacob Faibussowitsch   Fortran Notes:
3624a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3625a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
36263813dfbdSMatthew G Knepley 
36271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3628552f7358SJed Brown @*/
3629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3630d71ae5a4SJacob Faibussowitsch {
3631552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3632552f7358SJed Brown   PetscInt off;
3633552f7358SJed Brown 
3634552f7358SJed Brown   PetscFunctionBegin;
3635552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36364f572ea9SToby Isaac   PetscAssertPointer(support, 3);
36379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
36388e3a54c0SPierre Jolivet   *support = PetscSafePointerPlusOffset(mesh->supports, off);
36393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3640552f7358SJed Brown }
3641552f7358SJed Brown 
3642552f7358SJed Brown /*@
364392371b87SBarry 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
3644552f7358SJed Brown 
3645a1cb98faSBarry Smith   Not Collective
3646552f7358SJed Brown 
3647552f7358SJed Brown   Input Parameters:
364860225df5SJacob Faibussowitsch + dm      - The `DMPLEX`
3649a1cb98faSBarry Smith . p       - The point, which must lie in the chart set with `DMPlexSetChart()`
365020f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3651552f7358SJed Brown 
3652552f7358SJed Brown   Level: beginner
3653552f7358SJed Brown 
3654a1cb98faSBarry Smith   Note:
3655a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3656a1cb98faSBarry Smith 
36571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3658552f7358SJed Brown @*/
3659d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3660d71ae5a4SJacob Faibussowitsch {
3661552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3662552f7358SJed Brown   PetscInt pStart, pEnd;
3663552f7358SJed Brown   PetscInt dof, off, c;
3664552f7358SJed Brown 
3665552f7358SJed Brown   PetscFunctionBegin;
3666552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
36694f572ea9SToby Isaac   if (dof) PetscAssertPointer(support, 3);
36709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
367163a3b9bcSJacob 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);
3672552f7358SJed Brown   for (c = 0; c < dof; ++c) {
367363a3b9bcSJacob 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);
3674552f7358SJed Brown     mesh->supports[off + c] = support[c];
3675552f7358SJed Brown   }
36763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3677552f7358SJed Brown }
3678552f7358SJed Brown 
36797cd05799SMatthew G. Knepley /*@
3680eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
36817cd05799SMatthew G. Knepley 
3682a1cb98faSBarry Smith   Not Collective
36837cd05799SMatthew G. Knepley 
36847cd05799SMatthew G. Knepley   Input Parameters:
368560225df5SJacob Faibussowitsch + dm           - The `DMPLEX`
3686a1cb98faSBarry Smith . p            - The point, which must lie in the chart set with `DMPlexSetChart()`
36877cd05799SMatthew G. Knepley . supportPos   - The local index in the cone where the point should be put
36887cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
36897cd05799SMatthew G. Knepley 
36907cd05799SMatthew G. Knepley   Level: beginner
36917cd05799SMatthew G. Knepley 
36921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
36937cd05799SMatthew G. Knepley @*/
3694d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3695d71ae5a4SJacob Faibussowitsch {
3696552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3697552f7358SJed Brown   PetscInt pStart, pEnd;
3698552f7358SJed Brown   PetscInt dof, off;
3699552f7358SJed Brown 
3700552f7358SJed Brown   PetscFunctionBegin;
3701552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
37039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
37049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
370563a3b9bcSJacob 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);
370663a3b9bcSJacob 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);
370763a3b9bcSJacob 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);
3708552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
37093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3710552f7358SJed Brown }
3711552f7358SJed Brown 
3712b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3713d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3714d71ae5a4SJacob Faibussowitsch {
3715b5a892a1SMatthew G. Knepley   switch (ct) {
3716b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3717b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3718b5a892a1SMatthew G. Knepley     break;
3719b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3720b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3721b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3722b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3723b5a892a1SMatthew G. Knepley     break;
3724b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3725b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3726b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3727b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3728b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3729b5a892a1SMatthew G. Knepley     break;
3730d71ae5a4SJacob Faibussowitsch   default:
3731d71ae5a4SJacob Faibussowitsch     return o;
3732b5a892a1SMatthew G. Knepley   }
3733b5a892a1SMatthew G. Knepley   return o;
3734b5a892a1SMatthew G. Knepley }
3735b5a892a1SMatthew G. Knepley 
3736b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3737d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3738d71ae5a4SJacob Faibussowitsch {
3739b5a892a1SMatthew G. Knepley   switch (ct) {
3740b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3741b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3742b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3743b5a892a1SMatthew G. Knepley     break;
3744b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3745b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3746b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3747b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3748b5a892a1SMatthew G. Knepley     break;
3749b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3750b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3751b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3752b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3753b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3754b5a892a1SMatthew G. Knepley     break;
3755d71ae5a4SJacob Faibussowitsch   default:
3756d71ae5a4SJacob Faibussowitsch     return o;
3757b5a892a1SMatthew G. Knepley   }
3758b5a892a1SMatthew G. Knepley   return o;
3759b5a892a1SMatthew G. Knepley }
3760b5a892a1SMatthew G. Knepley 
3761b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3763d71ae5a4SJacob Faibussowitsch {
3764b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3765b5a892a1SMatthew G. Knepley 
3766b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
37679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3768b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3769b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3770b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3771b5a892a1SMatthew G. Knepley 
37729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
37739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
37749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3775b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3776b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3777b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3778b5a892a1SMatthew G. Knepley 
37799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3780b5a892a1SMatthew G. Knepley       switch (ct) {
3781b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
37829566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37839566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3784b5a892a1SMatthew G. Knepley         break;
3785b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
37869566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37879566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37889566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3789b5a892a1SMatthew G. Knepley         break;
3790b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
37919566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37929566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37939566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
37949566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3795b5a892a1SMatthew G. Knepley         break;
3796d71ae5a4SJacob Faibussowitsch       default:
3797d71ae5a4SJacob Faibussowitsch         break;
3798b5a892a1SMatthew G. Knepley       }
3799b5a892a1SMatthew G. Knepley     }
3800b5a892a1SMatthew G. Knepley   }
38013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3802b5a892a1SMatthew G. Knepley }
3803b5a892a1SMatthew G. Knepley 
380409015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
380509015e70SStefano Zampini {
380609015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
380709015e70SStefano Zampini 
380809015e70SStefano Zampini   PetscFunctionBeginHot;
380909015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
381009015e70SStefano Zampini     if (useCone) {
381109015e70SStefano Zampini       PetscCall(DMPlexGetConeSize(dm, p, size));
381209015e70SStefano Zampini       PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt));
381309015e70SStefano Zampini     } else {
381409015e70SStefano Zampini       PetscCall(DMPlexGetSupportSize(dm, p, size));
381509015e70SStefano Zampini       PetscCall(DMPlexGetSupport(dm, p, arr));
381609015e70SStefano Zampini     }
381709015e70SStefano Zampini   } else {
381809015e70SStefano Zampini     if (useCone) {
381909015e70SStefano Zampini       const PetscSection s   = mesh->coneSection;
382009015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
382109015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
382209015e70SStefano Zampini 
382309015e70SStefano Zampini       *size = s->atlasDof[ps];
382409015e70SStefano Zampini       *arr  = mesh->cones + off;
382509015e70SStefano Zampini       *ornt = mesh->coneOrientations + off;
382609015e70SStefano Zampini     } else {
382709015e70SStefano Zampini       const PetscSection s   = mesh->supportSection;
382809015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
382909015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
383009015e70SStefano Zampini 
383109015e70SStefano Zampini       *size = s->atlasDof[ps];
383209015e70SStefano Zampini       *arr  = mesh->supports + off;
383309015e70SStefano Zampini     }
383409015e70SStefano Zampini   }
383509015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
383609015e70SStefano Zampini }
383709015e70SStefano Zampini 
383809015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
383909015e70SStefano Zampini {
384009015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
384109015e70SStefano Zampini 
384209015e70SStefano Zampini   PetscFunctionBeginHot;
384309015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
384409015e70SStefano Zampini     if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt));
384509015e70SStefano Zampini   }
384609015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
384709015e70SStefano Zampini }
384809015e70SStefano Zampini 
3849d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3850d71ae5a4SJacob Faibussowitsch {
3851b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3852b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3853b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3854b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3855b5a892a1SMatthew G. Knepley 
3856b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3857b5a892a1SMatthew G. Knepley   if (ornt) {
38589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3859476787b7SMatthew 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;
3860b5a892a1SMatthew G. Knepley   }
3861b5a892a1SMatthew G. Knepley   if (*points) {
3862b5a892a1SMatthew G. Knepley     closure = *points;
3863b5a892a1SMatthew G. Knepley   } else {
3864b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
38659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
38669566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3867b5a892a1SMatthew G. Knepley   }
386809015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3869b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3870b5a892a1SMatthew G. Knepley     closure[off++] = p;
3871b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3872b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3873b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3874b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3875b5a892a1SMatthew G. Knepley     }
3876b5a892a1SMatthew G. Knepley   } else {
387785036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt);
3878b5a892a1SMatthew G. Knepley 
3879b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3880b5a892a1SMatthew G. Knepley     closure[off++] = p;
3881b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3882b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3883b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3884b5a892a1SMatthew G. Knepley 
38859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3886b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3887b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3888b5a892a1SMatthew G. Knepley     }
3889b5a892a1SMatthew G. Knepley   }
389009015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3891b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3892b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3894b5a892a1SMatthew G. Knepley }
3895b5a892a1SMatthew G. Knepley 
3896d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3897d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3898d71ae5a4SJacob Faibussowitsch {
389985036b15SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
3900b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3901b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3902b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3903b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3904b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3905b5a892a1SMatthew G. Knepley 
3906b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39079566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
390809015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
39099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3910b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3911b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3912b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39139371c9d4SSatish Balay   if (*points) {
39149371c9d4SSatish Balay     pts = *points;
39159371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3916b5a892a1SMatthew G. Knepley   c        = 0;
3917b5a892a1SMatthew G. Knepley   pts[c++] = point;
3918b5a892a1SMatthew G. Knepley   pts[c++] = o;
39199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
39209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
39219371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39229371c9d4SSatish Balay     pts[c++] = closure[cl];
39239371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39249371c9d4SSatish Balay   }
39259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
39269371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39279371c9d4SSatish Balay     pts[c++] = closure[cl];
39289371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39299371c9d4SSatish Balay   }
39309566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3931b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
39329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3933b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3934b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3935b5a892a1SMatthew G. Knepley   }
393609015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
3937b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3938b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3939b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3940b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3941b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3942b5a892a1SMatthew G. Knepley 
39439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
394485036b15SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
394509015e70SStefano Zampini       PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3946b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3947b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3948b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3949b5a892a1SMatthew G. Knepley 
39509371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
39519371c9d4SSatish Balay           if (pts[i] == cp) break;
3952b5a892a1SMatthew G. Knepley         if (i == c) {
39539566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3954b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3955b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3956b5a892a1SMatthew G. Knepley         }
3957b5a892a1SMatthew G. Knepley       }
395809015e70SStefano Zampini       PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3959b5a892a1SMatthew G. Knepley     }
3960b5a892a1SMatthew G. Knepley   }
3961b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3962b5a892a1SMatthew G. Knepley   *points    = pts;
39633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3964b5a892a1SMatthew G. Knepley }
3965b5a892a1SMatthew G. Knepley 
3966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3967d71ae5a4SJacob Faibussowitsch {
3968b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3969b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3970b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3971b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3972b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3973b5a892a1SMatthew G. Knepley 
3974b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3976b5a892a1SMatthew G. Knepley   if (depth == 1) {
39779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
39783ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3979b5a892a1SMatthew G. Knepley   }
39809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3981476787b7SMatthew 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;
3982c306944fSJed Brown   if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
39839566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
39843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3985b5a892a1SMatthew G. Knepley   }
39869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3987b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3988b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3989b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39909566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
39919371c9d4SSatish Balay   if (*points) {
39929371c9d4SSatish Balay     closure = *points;
39939371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3994b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3995b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3996b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3997b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3998b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3999b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
4000b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
4001b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
4002b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
4003b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
400485036b15SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangement(qt, o);
400509015e70SStefano Zampini     const PetscInt      *tmp, *tmpO = NULL;
4006b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
4007b5a892a1SMatthew G. Knepley 
4008b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
400985036b15SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2;
401063a3b9bcSJacob 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);
4011b5a892a1SMatthew G. Knepley     }
401209015e70SStefano Zampini     PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4013b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
4014b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
4015b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
4016b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
40179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
4018b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
4019b5a892a1SMatthew G. Knepley       PetscInt       c;
4020b5a892a1SMatthew G. Knepley 
4021b5a892a1SMatthew G. Knepley       /* Check for duplicate */
4022b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
4023b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
4024b5a892a1SMatthew G. Knepley       }
4025b5a892a1SMatthew G. Knepley       if (c == closureSize) {
4026b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
4027b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
4028b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
4029b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
4030b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
4031b5a892a1SMatthew G. Knepley       }
4032b5a892a1SMatthew G. Knepley     }
403309015e70SStefano Zampini     PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4034b5a892a1SMatthew G. Knepley   }
40359566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
4036b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
4037b5a892a1SMatthew G. Knepley   if (points) *points = closure;
40383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4039b5a892a1SMatthew G. Knepley }
4040b5a892a1SMatthew G. Knepley 
4041552f7358SJed Brown /*@C
4042eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
4043552f7358SJed Brown 
4044a1cb98faSBarry Smith   Not Collective
4045552f7358SJed Brown 
4046552f7358SJed Brown   Input Parameters:
4047a1cb98faSBarry Smith + dm      - The `DMPLEX`
4048b5a892a1SMatthew G. Knepley . p       - The mesh point
4049a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
4050552f7358SJed Brown 
40516b867d5aSJose E. Roman   Input/Output Parameter:
40526b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
405320f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
40546b867d5aSJose E. Roman 
40556b867d5aSJose E. Roman   Output Parameter:
405620f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4057552f7358SJed Brown 
4058a1cb98faSBarry Smith   Level: beginner
4059a1cb98faSBarry Smith 
4060552f7358SJed Brown   Note:
406120f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
4062552f7358SJed Brown 
406360225df5SJacob Faibussowitsch   Fortran Notes:
406420f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
40653813dfbdSMatthew G Knepley 
40661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4067552f7358SJed Brown @*/
4068d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4069d71ae5a4SJacob Faibussowitsch {
4070b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4071552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40724f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(numPoints, 4);
40734f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 5);
40749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
40753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40769bf0dad6SMatthew G. Knepley }
40779bf0dad6SMatthew G. Knepley 
4078552f7358SJed Brown /*@C
4079eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
4080552f7358SJed Brown 
4081a1cb98faSBarry Smith   Not Collective
4082552f7358SJed Brown 
4083552f7358SJed Brown   Input Parameters:
4084a1cb98faSBarry Smith + dm        - The `DMPLEX`
4085b5a892a1SMatthew G. Knepley . p         - The mesh point
4086a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
408720f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4088b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
4089552f7358SJed Brown 
4090a1cb98faSBarry Smith   Level: beginner
4091a1cb98faSBarry Smith 
4092552f7358SJed Brown   Note:
409320f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
4094552f7358SJed Brown 
40951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4096552f7358SJed Brown @*/
4097d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4098d71ae5a4SJacob Faibussowitsch {
4099b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4100552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41014ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
41029566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
41033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4104552f7358SJed Brown }
4105552f7358SJed Brown 
4106552f7358SJed Brown /*@
4107eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
4108552f7358SJed Brown 
4109a1cb98faSBarry Smith   Not Collective
4110552f7358SJed Brown 
4111552f7358SJed Brown   Input Parameter:
411260225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4113552f7358SJed Brown 
4114552f7358SJed Brown   Output Parameters:
4115552f7358SJed Brown + maxConeSize    - The maximum number of in-edges
4116552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
4117552f7358SJed Brown 
4118552f7358SJed Brown   Level: beginner
4119552f7358SJed Brown 
41201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
4121552f7358SJed Brown @*/
4122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
4123d71ae5a4SJacob Faibussowitsch {
4124552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
4125552f7358SJed Brown 
4126552f7358SJed Brown   PetscFunctionBegin;
4127552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41281baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
41291baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
41303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4131552f7358SJed Brown }
4132552f7358SJed Brown 
4133d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
4134d71ae5a4SJacob Faibussowitsch {
4135552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
41366302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
4137552f7358SJed Brown 
4138552f7358SJed Brown   PetscFunctionBegin;
4139552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
41419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
41429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
41439566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
41446302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41456302a7fbSVaclav Hapla   if (maxSupportSize) {
41469566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
41479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
41489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
4149552f7358SJed Brown   }
41503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4151552f7358SJed Brown }
4152552f7358SJed Brown 
4153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
4154d71ae5a4SJacob Faibussowitsch {
4155552f7358SJed Brown   PetscFunctionBegin;
41569566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
4157dd072f5fSMatthew G. Knepley   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm));
4158ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
4159736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
416095602cf2SAlexis Marboeuf     PetscSF sfNatural;
4161f94b4a02SBlaise Bourdin 
41623dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
41639566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
416495602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
4165c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
4166f94b4a02SBlaise Bourdin   }
41673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4168552f7358SJed Brown }
4169552f7358SJed Brown 
4170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
4171d71ae5a4SJacob Faibussowitsch {
41723dcd263cSBlaise Bourdin   PetscInt i = 0;
41732adcc780SMatthew G. Knepley 
41742adcc780SMatthew G. Knepley   PetscFunctionBegin;
41759566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
41769566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
4177c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
41783dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
41793dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
418095602cf2SAlexis Marboeuf       PetscSF sfNatural;
41813dcd263cSBlaise Bourdin 
41823dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
41839566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
4184c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
418595602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
4186c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
41873dcd263cSBlaise Bourdin       break;
41883dcd263cSBlaise Bourdin     }
41893dcd263cSBlaise Bourdin   }
41903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41912adcc780SMatthew G. Knepley }
41922adcc780SMatthew G. Knepley 
4193552f7358SJed Brown /*@
4194eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
4195552f7358SJed Brown 
4196a1cb98faSBarry Smith   Not Collective
4197552f7358SJed Brown 
4198552f7358SJed Brown   Input Parameter:
419960225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4200552f7358SJed Brown 
4201552f7358SJed Brown   Level: beginner
4202552f7358SJed Brown 
4203a1cb98faSBarry Smith   Note:
4204a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
4205a1cb98faSBarry Smith 
42061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
4207552f7358SJed Brown @*/
4208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
4209d71ae5a4SJacob Faibussowitsch {
4210552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4211552f7358SJed Brown   PetscInt *offsets;
4212552f7358SJed Brown   PetscInt  supportSize;
4213552f7358SJed Brown   PetscInt  pStart, pEnd, p;
4214552f7358SJed Brown 
4215552f7358SJed Brown   PetscFunctionBegin;
4216552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
421728b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
42189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
4219552f7358SJed Brown   /* Calculate support sizes */
42209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4221552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4222552f7358SJed Brown     PetscInt dof, off, c;
4223552f7358SJed Brown 
42249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
422648a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4227552f7358SJed Brown   }
42289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4229552f7358SJed Brown   /* Calculate supports */
42309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
42319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
42329566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4233552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4234552f7358SJed Brown     PetscInt dof, off, c;
4235552f7358SJed Brown 
42369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4238552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4239552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4240552f7358SJed Brown       PetscInt       offS;
4241552f7358SJed Brown 
42429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
42430d644c17SKarl Rupp 
4244552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4245552f7358SJed Brown       ++offsets[q];
4246552f7358SJed Brown     }
4247552f7358SJed Brown   }
42489566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
42499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
42503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4251552f7358SJed Brown }
4252552f7358SJed Brown 
4253d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4254d71ae5a4SJacob Faibussowitsch {
4255277ea44aSLisandro Dalcin   IS stratumIS;
4256277ea44aSLisandro Dalcin 
4257277ea44aSLisandro Dalcin   PetscFunctionBegin;
42583ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
425976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4260277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4261277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
42629566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4263277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
42649566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
42659371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
42669371c9d4SSatish Balay         overlap = PETSC_TRUE;
42679371c9d4SSatish Balay         break;
42689371c9d4SSatish Balay       }
4269277ea44aSLisandro Dalcin     }
427063a3b9bcSJacob 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);
4271277ea44aSLisandro Dalcin   }
42729566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
42739566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
42749566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
42753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4276277ea44aSLisandro Dalcin }
4277277ea44aSLisandro Dalcin 
4278e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label)
4279e91fa0a1SMatthew G. Knepley {
4280e91fa0a1SMatthew G. Knepley   PetscInt *pMin, *pMax;
4281e91fa0a1SMatthew G. Knepley   PetscInt  pStart, pEnd;
4282e91fa0a1SMatthew G. Knepley   PetscInt  dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT;
4283e91fa0a1SMatthew G. Knepley 
4284e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4285e91fa0a1SMatthew G. Knepley   {
4286e91fa0a1SMatthew G. Knepley     DMLabel label2;
4287e91fa0a1SMatthew G. Knepley 
4288e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellTypeLabel(dm, &label2));
4289e91fa0a1SMatthew G. Knepley     PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view"));
4290e91fa0a1SMatthew G. Knepley   }
4291e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4292e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4293e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4294e91fa0a1SMatthew G. Knepley 
4295e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4296e91fa0a1SMatthew G. Knepley     dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin);
4297e91fa0a1SMatthew G. Knepley     dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax);
4298e91fa0a1SMatthew G. Knepley   }
4299e91fa0a1SMatthew G. Knepley   PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax));
4300e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4301e91fa0a1SMatthew G. Knepley     pMin[d] = PETSC_MAX_INT;
4302e91fa0a1SMatthew G. Knepley     pMax[d] = PETSC_MIN_INT;
4303e91fa0a1SMatthew G. Knepley   }
4304e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4305e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4306e91fa0a1SMatthew G. Knepley     PetscInt       d;
4307e91fa0a1SMatthew G. Knepley 
4308e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4309e91fa0a1SMatthew G. Knepley     d       = DMPolytopeTypeGetDim(ct);
4310e91fa0a1SMatthew G. Knepley     pMin[d] = PetscMin(p, pMin[d]);
4311e91fa0a1SMatthew G. Knepley     pMax[d] = PetscMax(p, pMax[d]);
4312e91fa0a1SMatthew G. Knepley   }
4313e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4314e91fa0a1SMatthew G. Knepley     if (pMin[d] > pMax[d]) continue;
4315e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1));
4316e91fa0a1SMatthew G. Knepley   }
4317e91fa0a1SMatthew G. Knepley   PetscCall(PetscFree2(pMin, pMax));
4318e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4319e91fa0a1SMatthew G. Knepley }
4320e91fa0a1SMatthew G. Knepley 
4321e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label)
4322e91fa0a1SMatthew G. Knepley {
4323e91fa0a1SMatthew G. Knepley   PetscInt pStart, pEnd;
4324e91fa0a1SMatthew G. Knepley   PetscInt numRoots = 0, numLeaves = 0;
4325e91fa0a1SMatthew G. Knepley 
4326e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4327e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4328e91fa0a1SMatthew G. Knepley   {
4329e91fa0a1SMatthew G. Knepley     /* Initialize roots and count leaves */
4330e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4331e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4332e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4333e91fa0a1SMatthew G. Knepley 
4334e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4335e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4336e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4337e91fa0a1SMatthew G. Knepley       if (!coneSize && supportSize) {
4338e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4339e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4340e91fa0a1SMatthew G. Knepley         ++numRoots;
4341e91fa0a1SMatthew G. Knepley       } else if (!supportSize && coneSize) {
4342e91fa0a1SMatthew G. Knepley         ++numLeaves;
4343e91fa0a1SMatthew G. Knepley       } else if (!supportSize && !coneSize) {
4344e91fa0a1SMatthew G. Knepley         /* Isolated points */
4345e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4346e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4347e91fa0a1SMatthew G. Knepley       }
4348e91fa0a1SMatthew G. Knepley     }
4349e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4350e91fa0a1SMatthew G. Knepley   }
4351e91fa0a1SMatthew G. Knepley 
4352e91fa0a1SMatthew G. Knepley   if (numRoots + numLeaves == (pEnd - pStart)) {
4353e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4354e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4355e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4356e91fa0a1SMatthew G. Knepley 
4357e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4358e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4359e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4360e91fa0a1SMatthew G. Knepley       if (!supportSize && coneSize) {
4361e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4362e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4363e91fa0a1SMatthew G. Knepley       }
4364e91fa0a1SMatthew G. Knepley     }
4365e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4366e91fa0a1SMatthew G. Knepley   } else {
4367e91fa0a1SMatthew G. Knepley     PetscInt level = 0;
4368e91fa0a1SMatthew G. Knepley     PetscInt qStart, qEnd;
4369e91fa0a1SMatthew G. Knepley 
4370e91fa0a1SMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4371e91fa0a1SMatthew G. Knepley     while (qEnd > qStart) {
4372e91fa0a1SMatthew G. Knepley       PetscInt sMin = PETSC_MAX_INT;
4373e91fa0a1SMatthew G. Knepley       PetscInt sMax = PETSC_MIN_INT;
4374e91fa0a1SMatthew G. Knepley 
4375e91fa0a1SMatthew G. Knepley       for (PetscInt q = qStart; q < qEnd; ++q) {
4376e91fa0a1SMatthew G. Knepley         const PetscInt *support;
4377e91fa0a1SMatthew G. Knepley         PetscInt        supportSize;
4378e91fa0a1SMatthew G. Knepley 
4379e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
4380e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupport(dm, q, &support));
4381e91fa0a1SMatthew G. Knepley         for (PetscInt s = 0; s < supportSize; ++s) {
4382e91fa0a1SMatthew G. Knepley           sMin = PetscMin(support[s], sMin);
4383e91fa0a1SMatthew G. Knepley           sMax = PetscMax(support[s], sMax);
4384e91fa0a1SMatthew G. Knepley         }
4385e91fa0a1SMatthew G. Knepley       }
4386e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetNumValues(label, &level));
4387e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
4388e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4389e91fa0a1SMatthew G. Knepley     }
4390e91fa0a1SMatthew G. Knepley   }
4391e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4392e91fa0a1SMatthew G. Knepley }
4393e91fa0a1SMatthew G. Knepley 
4394552f7358SJed Brown /*@
4395a4e35b19SJacob Faibussowitsch   DMPlexStratify - Computes the strata for all points in the `DMPLEX`
4396552f7358SJed Brown 
439720f4b53cSBarry Smith   Collective
4398552f7358SJed Brown 
4399552f7358SJed Brown   Input Parameter:
440060225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4401552f7358SJed Brown 
4402a1cb98faSBarry Smith   Level: beginner
4403552f7358SJed Brown 
4404552f7358SJed Brown   Notes:
4405a4e35b19SJacob Faibussowitsch   The strata group all points of the same grade, and this function calculates the strata. This
4406a4e35b19SJacob Faibussowitsch   grade can be seen as the height (or depth) of the point in the DAG.
4407a4e35b19SJacob Faibussowitsch 
4408a4e35b19SJacob Faibussowitsch   The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
4409a4e35b19SJacob Faibussowitsch   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram).
4410a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4411b1bb481bSMatthew 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
4412a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4413a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4414a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4415552f7358SJed Brown 
4416b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4417b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4418b1bb481bSMatthew 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
4419b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4420a1cb98faSBarry Smith .vb
4421a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4422a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4423a1cb98faSBarry Smith .ve
4424a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4425a1cb98faSBarry Smith .vb
4426a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4427a1cb98faSBarry Smith    depth 1 = {e0, c0}
4428a1cb98faSBarry Smith .ve
4429b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4430b1bb481bSMatthew Knepley 
4431a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4432552f7358SJed Brown 
44331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4434552f7358SJed Brown @*/
4435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4436d71ae5a4SJacob Faibussowitsch {
4437df0420ecSMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
4438aa50250dSMatthew G. Knepley   DMLabel   label;
4439e91fa0a1SMatthew G. Knepley   PetscBool flg = PETSC_FALSE;
4440552f7358SJed Brown 
4441552f7358SJed Brown   PetscFunctionBegin;
4442552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44439566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4444277ea44aSLisandro Dalcin 
4445e91fa0a1SMatthew G. Knepley   // Create depth label
4446d28dd301SMatthew G. Knepley   PetscCall(DMRemoveLabel(dm, "depth", NULL));
44479566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
44489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4449277ea44aSLisandro Dalcin 
4450e91fa0a1SMatthew G. Knepley   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL));
4451e91fa0a1SMatthew G. Knepley   if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label));
4452e91fa0a1SMatthew G. Knepley   else PetscCall(DMPlexStratify_Topological_Private(dm, label));
4453552f7358SJed Brown 
4454bf4602e4SToby Isaac   { /* just in case there is an empty process */
4455bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4456bf4602e4SToby Isaac 
44579566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4458712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
445948a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4460bf4602e4SToby Isaac   }
44619566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
44629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
44633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4464552f7358SJed Brown }
4465552f7358SJed Brown 
4466d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4467d71ae5a4SJacob Faibussowitsch {
4468412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4469412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4470ba2698f1SMatthew G. Knepley 
4471412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
44729566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
44739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
44749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4475ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4476ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4477ba2698f1SMatthew G. Knepley     switch (pdepth) {
4478d71ae5a4SJacob Faibussowitsch     case 0:
4479d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4480d71ae5a4SJacob Faibussowitsch       break;
4481ba2698f1SMatthew G. Knepley     case 1:
4482ba2698f1SMatthew G. Knepley       switch (coneSize) {
4483d71ae5a4SJacob Faibussowitsch       case 2:
4484d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4485d71ae5a4SJacob Faibussowitsch         break;
4486d71ae5a4SJacob Faibussowitsch       case 3:
4487d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4488d71ae5a4SJacob Faibussowitsch         break;
4489ba2698f1SMatthew G. Knepley       case 4:
4490ba2698f1SMatthew G. Knepley         switch (dim) {
4491d71ae5a4SJacob Faibussowitsch         case 2:
4492d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4493d71ae5a4SJacob Faibussowitsch           break;
4494d71ae5a4SJacob Faibussowitsch         case 3:
4495d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4496d71ae5a4SJacob Faibussowitsch           break;
4497d71ae5a4SJacob Faibussowitsch         default:
4498d71ae5a4SJacob Faibussowitsch           break;
4499ba2698f1SMatthew G. Knepley         }
4500ba2698f1SMatthew G. Knepley         break;
4501d71ae5a4SJacob Faibussowitsch       case 5:
4502d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4503d71ae5a4SJacob Faibussowitsch         break;
4504d71ae5a4SJacob Faibussowitsch       case 6:
4505d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4506d71ae5a4SJacob Faibussowitsch         break;
4507d71ae5a4SJacob Faibussowitsch       case 8:
4508d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4509d71ae5a4SJacob Faibussowitsch         break;
4510d71ae5a4SJacob Faibussowitsch       default:
4511d71ae5a4SJacob Faibussowitsch         break;
4512ba2698f1SMatthew G. Knepley       }
4513ba2698f1SMatthew G. Knepley     }
4514ba2698f1SMatthew G. Knepley   } else {
4515ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4516ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4517ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4518ba2698f1SMatthew G. Knepley       switch (dim) {
4519ba2698f1SMatthew G. Knepley       case 1:
4520ba2698f1SMatthew G. Knepley         switch (coneSize) {
4521d71ae5a4SJacob Faibussowitsch         case 2:
4522d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4523d71ae5a4SJacob Faibussowitsch           break;
4524d71ae5a4SJacob Faibussowitsch         default:
4525d71ae5a4SJacob Faibussowitsch           break;
4526ba2698f1SMatthew G. Knepley         }
4527ba2698f1SMatthew G. Knepley         break;
4528ba2698f1SMatthew G. Knepley       case 2:
4529ba2698f1SMatthew G. Knepley         switch (coneSize) {
4530d71ae5a4SJacob Faibussowitsch         case 3:
4531d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4532d71ae5a4SJacob Faibussowitsch           break;
4533d71ae5a4SJacob Faibussowitsch         case 4:
4534d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4535d71ae5a4SJacob Faibussowitsch           break;
4536d71ae5a4SJacob Faibussowitsch         default:
4537d71ae5a4SJacob Faibussowitsch           break;
4538ba2698f1SMatthew G. Knepley         }
4539ba2698f1SMatthew G. Knepley         break;
4540ba2698f1SMatthew G. Knepley       case 3:
4541ba2698f1SMatthew G. Knepley         switch (coneSize) {
4542d71ae5a4SJacob Faibussowitsch         case 4:
4543d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4544d71ae5a4SJacob Faibussowitsch           break;
45459371c9d4SSatish Balay         case 5: {
4546da9060c4SMatthew G. Knepley           const PetscInt *cone;
4547da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4548da9060c4SMatthew G. Knepley 
45499566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
45509566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4551da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4552d71ae5a4SJacob Faibussowitsch           case 3:
4553d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4554d71ae5a4SJacob Faibussowitsch             break;
4555d71ae5a4SJacob Faibussowitsch           case 4:
4556d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4557d71ae5a4SJacob Faibussowitsch             break;
4558da9060c4SMatthew G. Knepley           }
45599371c9d4SSatish Balay         } break;
4560d71ae5a4SJacob Faibussowitsch         case 6:
4561d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4562d71ae5a4SJacob Faibussowitsch           break;
4563d71ae5a4SJacob Faibussowitsch         default:
4564d71ae5a4SJacob Faibussowitsch           break;
4565ba2698f1SMatthew G. Knepley         }
4566ba2698f1SMatthew G. Knepley         break;
4567d71ae5a4SJacob Faibussowitsch       default:
4568d71ae5a4SJacob Faibussowitsch         break;
4569ba2698f1SMatthew G. Knepley       }
4570ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4571ba2698f1SMatthew G. Knepley       switch (coneSize) {
4572d71ae5a4SJacob Faibussowitsch       case 2:
4573d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4574d71ae5a4SJacob Faibussowitsch         break;
4575d71ae5a4SJacob Faibussowitsch       case 3:
4576d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4577d71ae5a4SJacob Faibussowitsch         break;
4578d71ae5a4SJacob Faibussowitsch       case 4:
4579d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4580d71ae5a4SJacob Faibussowitsch         break;
4581d71ae5a4SJacob Faibussowitsch       default:
4582d71ae5a4SJacob Faibussowitsch         break;
4583ba2698f1SMatthew G. Knepley       }
4584ba2698f1SMatthew G. Knepley     }
4585ba2698f1SMatthew G. Knepley   }
4586412e9a14SMatthew G. Knepley   *pt = ct;
45873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4588ba2698f1SMatthew G. Knepley }
4589412e9a14SMatthew G. Knepley 
4590412e9a14SMatthew G. Knepley /*@
4591412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4592412e9a14SMatthew G. Knepley 
459320f4b53cSBarry Smith   Collective
4594412e9a14SMatthew G. Knepley 
4595412e9a14SMatthew G. Knepley   Input Parameter:
459660225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4597412e9a14SMatthew G. Knepley 
4598412e9a14SMatthew G. Knepley   Level: developer
4599412e9a14SMatthew G. Knepley 
4600a1cb98faSBarry Smith   Note:
4601a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4602a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4603a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4604412e9a14SMatthew G. Knepley 
4605a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4606a1cb98faSBarry Smith 
46071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4608412e9a14SMatthew G. Knepley @*/
4609d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4610d71ae5a4SJacob Faibussowitsch {
4611412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4612412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4613412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4614412e9a14SMatthew G. Knepley 
4615412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4616412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4617412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
46189566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
46199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
46209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
462121027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
462221027e53SStefano Zampini   PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
4623412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4624327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4625412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4626412e9a14SMatthew G. Knepley 
46279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
46289566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
4629476787b7SMatthew 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);
46309566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
463121027e53SStefano Zampini     mesh->cellTypes[p - pStart].value_as_uint8 = ct;
4632412e9a14SMatthew G. Knepley   }
46339566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
46349566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
46353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4636ba2698f1SMatthew G. Knepley }
4637ba2698f1SMatthew G. Knepley 
4638552f7358SJed Brown /*@C
4639552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4640552f7358SJed Brown 
4641552f7358SJed Brown   Not Collective
4642552f7358SJed Brown 
4643552f7358SJed Brown   Input Parameters:
4644a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4645552f7358SJed Brown . numPoints - The number of input points for the join
4646552f7358SJed Brown - points    - The input points
4647552f7358SJed Brown 
4648552f7358SJed Brown   Output Parameters:
4649552f7358SJed Brown + numCoveredPoints - The number of points in the join
4650552f7358SJed Brown - coveredPoints    - The points in the join
4651552f7358SJed Brown 
4652552f7358SJed Brown   Level: intermediate
4653552f7358SJed Brown 
4654a1cb98faSBarry Smith   Note:
4655a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4656552f7358SJed Brown 
465760225df5SJacob Faibussowitsch   Fortran Notes:
465820f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46593813dfbdSMatthew G Knepley 
46601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4661552f7358SJed Brown @*/
4662d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4663d71ae5a4SJacob Faibussowitsch {
4664552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4665552f7358SJed Brown   PetscInt *join[2];
4666552f7358SJed Brown   PetscInt  joinSize, i = 0;
4667552f7358SJed Brown   PetscInt  dof, off, p, c, m;
46686302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4669552f7358SJed Brown 
4670552f7358SJed Brown   PetscFunctionBegin;
4671552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46724f572ea9SToby Isaac   PetscAssertPointer(points, 3);
46734f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
46744f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
46756302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
46766302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
46776302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4678552f7358SJed Brown   /* Copy in support of first point */
46799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
46809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4681ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4682552f7358SJed Brown   /* Check each successive support */
4683552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4684552f7358SJed Brown     PetscInt newJoinSize = 0;
4685552f7358SJed Brown 
46869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
46879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4688552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4689552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4690552f7358SJed Brown 
4691552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4692552f7358SJed Brown         if (point == join[i][m]) {
4693552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4694552f7358SJed Brown           break;
4695552f7358SJed Brown         }
4696552f7358SJed Brown       }
4697552f7358SJed Brown     }
4698552f7358SJed Brown     joinSize = newJoinSize;
4699552f7358SJed Brown     i        = 1 - i;
4700552f7358SJed Brown   }
4701552f7358SJed Brown   *numCoveredPoints = joinSize;
4702552f7358SJed Brown   *coveredPoints    = join[i];
47036302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
47043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4705552f7358SJed Brown }
4706552f7358SJed Brown 
4707552f7358SJed Brown /*@C
4708552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4709552f7358SJed Brown 
4710552f7358SJed Brown   Not Collective
4711552f7358SJed Brown 
4712552f7358SJed Brown   Input Parameters:
4713a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4714552f7358SJed Brown . numPoints - The number of input points for the join
4715552f7358SJed Brown - points    - The input points
4716552f7358SJed Brown 
4717552f7358SJed Brown   Output Parameters:
4718552f7358SJed Brown + numCoveredPoints - The number of points in the join
4719552f7358SJed Brown - coveredPoints    - The points in the join
4720552f7358SJed Brown 
4721552f7358SJed Brown   Level: intermediate
4722552f7358SJed Brown 
472360225df5SJacob Faibussowitsch   Fortran Notes:
472420f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4725a1cb98faSBarry Smith 
47261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4727552f7358SJed Brown @*/
4728d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4729d71ae5a4SJacob Faibussowitsch {
4730552f7358SJed Brown   PetscFunctionBegin;
4731552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47324f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
47334f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
47344f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
47359566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4736d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
47373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4738552f7358SJed Brown }
4739552f7358SJed Brown 
4740552f7358SJed Brown /*@C
4741552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4742552f7358SJed Brown 
4743552f7358SJed Brown   Not Collective
4744552f7358SJed Brown 
4745552f7358SJed Brown   Input Parameters:
4746a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4747552f7358SJed Brown . numPoints - The number of input points for the join
4748552f7358SJed Brown - points    - The input points
4749552f7358SJed Brown 
4750552f7358SJed Brown   Output Parameters:
4751552f7358SJed Brown + numCoveredPoints - The number of points in the join
4752552f7358SJed Brown - coveredPoints    - The points in the join
4753552f7358SJed Brown 
4754552f7358SJed Brown   Level: intermediate
4755552f7358SJed Brown 
475660225df5SJacob Faibussowitsch   Fortran Notes:
475720f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4758a1cb98faSBarry Smith 
47591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4760552f7358SJed Brown @*/
4761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4762d71ae5a4SJacob Faibussowitsch {
4763552f7358SJed Brown   PetscInt *offsets, **closures;
4764552f7358SJed Brown   PetscInt *join[2];
4765552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
476624c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4767552f7358SJed Brown 
4768552f7358SJed Brown   PetscFunctionBegin;
4769552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47704f572ea9SToby Isaac   PetscAssertPointer(points, 3);
47714f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
47724f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4773552f7358SJed Brown 
47749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
47759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
47769566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
47776302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
477824c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
47799566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
47809566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4781552f7358SJed Brown 
4782552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4783552f7358SJed Brown     PetscInt closureSize;
4784552f7358SJed Brown 
47859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
47860d644c17SKarl Rupp 
4787552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4788552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4789552f7358SJed Brown       PetscInt pStart, pEnd, i;
4790552f7358SJed Brown 
47919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4792552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4793552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4794552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4795552f7358SJed Brown           break;
4796552f7358SJed Brown         }
4797552f7358SJed Brown       }
4798552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4799552f7358SJed Brown     }
480063a3b9bcSJacob 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);
4801552f7358SJed Brown   }
4802552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4803552f7358SJed Brown     PetscInt dof;
4804552f7358SJed Brown 
4805552f7358SJed Brown     /* Copy in support of first point */
4806552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4807ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4808552f7358SJed Brown     /* Check each successive cone */
4809552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4810552f7358SJed Brown       PetscInt newJoinSize = 0;
4811552f7358SJed Brown 
4812552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4813552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4814552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4815552f7358SJed Brown 
4816552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4817552f7358SJed Brown           if (point == join[i][m]) {
4818552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4819552f7358SJed Brown             break;
4820552f7358SJed Brown           }
4821552f7358SJed Brown         }
4822552f7358SJed Brown       }
4823552f7358SJed Brown       joinSize = newJoinSize;
4824552f7358SJed Brown       i        = 1 - i;
4825552f7358SJed Brown     }
4826552f7358SJed Brown     if (joinSize) break;
4827552f7358SJed Brown   }
4828552f7358SJed Brown   *numCoveredPoints = joinSize;
4829552f7358SJed Brown   *coveredPoints    = join[i];
483048a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
48319566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
48329566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
48336302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
48343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4835552f7358SJed Brown }
4836552f7358SJed Brown 
4837552f7358SJed Brown /*@C
4838552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4839552f7358SJed Brown 
4840552f7358SJed Brown   Not Collective
4841552f7358SJed Brown 
4842552f7358SJed Brown   Input Parameters:
4843a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4844552f7358SJed Brown . numPoints - The number of input points for the meet
4845552f7358SJed Brown - points    - The input points
4846552f7358SJed Brown 
4847552f7358SJed Brown   Output Parameters:
484860225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet
484960225df5SJacob Faibussowitsch - coveringPoints    - The points in the meet
4850552f7358SJed Brown 
4851552f7358SJed Brown   Level: intermediate
4852552f7358SJed Brown 
4853a1cb98faSBarry Smith   Note:
4854a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4855552f7358SJed Brown 
48563813dfbdSMatthew G Knepley   Fortran Notes:
485720f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
48583813dfbdSMatthew G Knepley 
48591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4860552f7358SJed Brown @*/
4861d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4862d71ae5a4SJacob Faibussowitsch {
4863552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4864552f7358SJed Brown   PetscInt *meet[2];
4865552f7358SJed Brown   PetscInt  meetSize, i = 0;
4866552f7358SJed Brown   PetscInt  dof, off, p, c, m;
48676302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4868552f7358SJed Brown 
4869552f7358SJed Brown   PetscFunctionBegin;
4870552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48714f572ea9SToby Isaac   PetscAssertPointer(points, 3);
48724f572ea9SToby Isaac   PetscAssertPointer(numCoveringPoints, 4);
48734f572ea9SToby Isaac   PetscAssertPointer(coveringPoints, 5);
48746302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
48756302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
48766302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4877552f7358SJed Brown   /* Copy in cone of first point */
48789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
48799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4880ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4881552f7358SJed Brown   /* Check each successive cone */
4882552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4883552f7358SJed Brown     PetscInt newMeetSize = 0;
4884552f7358SJed Brown 
48859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
48869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4887552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4888552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4889552f7358SJed Brown 
4890552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4891552f7358SJed Brown         if (point == meet[i][m]) {
4892552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4893552f7358SJed Brown           break;
4894552f7358SJed Brown         }
4895552f7358SJed Brown       }
4896552f7358SJed Brown     }
4897552f7358SJed Brown     meetSize = newMeetSize;
4898552f7358SJed Brown     i        = 1 - i;
4899552f7358SJed Brown   }
4900552f7358SJed Brown   *numCoveringPoints = meetSize;
4901552f7358SJed Brown   *coveringPoints    = meet[i];
49026302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
49033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4904552f7358SJed Brown }
4905552f7358SJed Brown 
4906552f7358SJed Brown /*@C
4907552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4908552f7358SJed Brown 
4909552f7358SJed Brown   Not Collective
4910552f7358SJed Brown 
4911552f7358SJed Brown   Input Parameters:
4912a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4913552f7358SJed Brown . numPoints - The number of input points for the meet
4914552f7358SJed Brown - points    - The input points
4915552f7358SJed Brown 
4916552f7358SJed Brown   Output Parameters:
4917552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4918552f7358SJed Brown - coveredPoints    - The points in the meet
4919552f7358SJed Brown 
4920552f7358SJed Brown   Level: intermediate
4921552f7358SJed Brown 
492260225df5SJacob Faibussowitsch   Fortran Notes:
492320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
49243813dfbdSMatthew G Knepley 
49251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4926552f7358SJed Brown @*/
4927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4928d71ae5a4SJacob Faibussowitsch {
4929552f7358SJed Brown   PetscFunctionBegin;
4930552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49314f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
49324f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
49334f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
49349566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4935d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
49363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4937552f7358SJed Brown }
4938552f7358SJed Brown 
4939552f7358SJed Brown /*@C
4940552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4941552f7358SJed Brown 
4942552f7358SJed Brown   Not Collective
4943552f7358SJed Brown 
4944552f7358SJed Brown   Input Parameters:
4945a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4946552f7358SJed Brown . numPoints - The number of input points for the meet
4947552f7358SJed Brown - points    - The input points
4948552f7358SJed Brown 
4949552f7358SJed Brown   Output Parameters:
4950552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4951552f7358SJed Brown - coveredPoints    - The points in the meet
4952552f7358SJed Brown 
4953552f7358SJed Brown   Level: intermediate
4954552f7358SJed Brown 
495560225df5SJacob Faibussowitsch   Fortran Notes:
495620f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
49573813dfbdSMatthew G Knepley 
49581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4959552f7358SJed Brown @*/
4960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4961d71ae5a4SJacob Faibussowitsch {
4962552f7358SJed Brown   PetscInt *offsets, **closures;
4963552f7358SJed Brown   PetscInt *meet[2];
4964552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
496524c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4966552f7358SJed Brown 
4967552f7358SJed Brown   PetscFunctionBegin;
4968552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49694f572ea9SToby Isaac   PetscAssertPointer(points, 3);
49704f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
49714f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4972552f7358SJed Brown 
49739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
49749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
49759566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
49766302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
497724c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
49789566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
49799566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4980552f7358SJed Brown 
4981552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4982552f7358SJed Brown     PetscInt closureSize;
4983552f7358SJed Brown 
49849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
49850d644c17SKarl Rupp 
4986552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4987552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4988552f7358SJed Brown       PetscInt pStart, pEnd, i;
4989552f7358SJed Brown 
49909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4991552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4992552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4993552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4994552f7358SJed Brown           break;
4995552f7358SJed Brown         }
4996552f7358SJed Brown       }
4997552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4998552f7358SJed Brown     }
499963a3b9bcSJacob 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);
5000552f7358SJed Brown   }
5001552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
5002552f7358SJed Brown     PetscInt dof;
5003552f7358SJed Brown 
5004552f7358SJed Brown     /* Copy in cone of first point */
5005552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
5006ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
5007552f7358SJed Brown     /* Check each successive cone */
5008552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
5009552f7358SJed Brown       PetscInt newMeetSize = 0;
5010552f7358SJed Brown 
5011552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
5012552f7358SJed Brown       for (c = 0; c < dof; ++c) {
5013552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
5014552f7358SJed Brown 
5015552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
5016552f7358SJed Brown           if (point == meet[i][m]) {
5017552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
5018552f7358SJed Brown             break;
5019552f7358SJed Brown           }
5020552f7358SJed Brown         }
5021552f7358SJed Brown       }
5022552f7358SJed Brown       meetSize = newMeetSize;
5023552f7358SJed Brown       i        = 1 - i;
5024552f7358SJed Brown     }
5025552f7358SJed Brown     if (meetSize) break;
5026552f7358SJed Brown   }
5027552f7358SJed Brown   *numCoveredPoints = meetSize;
5028552f7358SJed Brown   *coveredPoints    = meet[i];
502948a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
50309566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
50319566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
50326302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
50333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5034552f7358SJed Brown }
5035552f7358SJed Brown 
50364e3744c5SMatthew G. Knepley /*@C
5037a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
50384e3744c5SMatthew G. Knepley 
50394e3744c5SMatthew G. Knepley   Not Collective
50404e3744c5SMatthew G. Knepley 
50414e3744c5SMatthew G. Knepley   Input Parameters:
5042a1cb98faSBarry Smith + dmA - A `DMPLEX` object
5043a1cb98faSBarry Smith - dmB - A `DMPLEX` object
50444e3744c5SMatthew G. Knepley 
50452fe279fdSBarry Smith   Output Parameter:
5046a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
50474e3744c5SMatthew G. Knepley 
50484e3744c5SMatthew G. Knepley   Level: intermediate
50494e3744c5SMatthew G. Knepley 
5050a1cb98faSBarry Smith   Note:
50513c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
50524e3744c5SMatthew G. Knepley 
50531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
50544e3744c5SMatthew G. Knepley @*/
5055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
5056d71ae5a4SJacob Faibussowitsch {
50574e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
50584e3744c5SMatthew G. Knepley 
50594e3744c5SMatthew G. Knepley   PetscFunctionBegin;
50604e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
50614e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
50624f572ea9SToby Isaac   PetscAssertPointer(equal, 3);
50634e3744c5SMatthew G. Knepley 
50644e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
50659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
50669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
50673ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
50689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
50699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
50703ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
50714e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
50724e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
50734e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
50744e3744c5SMatthew G. Knepley 
50759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
50769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
50779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
50789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
50799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
50809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
50813ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
50824e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
50833ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
50843ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
50854e3744c5SMatthew G. Knepley     }
50869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
50879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
50889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
50899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
50903ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
50914e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
50923ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
50934e3744c5SMatthew G. Knepley     }
50944e3744c5SMatthew G. Knepley   }
50954e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
50963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50974e3744c5SMatthew G. Knepley }
50984e3744c5SMatthew G. Knepley 
50997cd05799SMatthew G. Knepley /*@C
51007cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
51017cd05799SMatthew G. Knepley 
51027cd05799SMatthew G. Knepley   Not Collective
51037cd05799SMatthew G. Knepley 
51047cd05799SMatthew G. Knepley   Input Parameters:
5105a1cb98faSBarry Smith + dm         - The `DMPLEX`
51067cd05799SMatthew G. Knepley . cellDim    - The cell dimension
51077cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
51087cd05799SMatthew G. Knepley 
51092fe279fdSBarry Smith   Output Parameter:
51107cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
51117cd05799SMatthew G. Knepley 
51127cd05799SMatthew G. Knepley   Level: developer
51137cd05799SMatthew G. Knepley 
5114a1cb98faSBarry Smith   Note:
51157cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
51167cd05799SMatthew G. Knepley 
51171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
51187cd05799SMatthew G. Knepley @*/
5119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
5120d71ae5a4SJacob Faibussowitsch {
512182f516ccSBarry Smith   MPI_Comm comm;
5122552f7358SJed Brown 
5123552f7358SJed Brown   PetscFunctionBegin;
51249566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
51254f572ea9SToby Isaac   PetscAssertPointer(numFaceVertices, 4);
5126552f7358SJed Brown   switch (cellDim) {
5127d71ae5a4SJacob Faibussowitsch   case 0:
5128d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
5129d71ae5a4SJacob Faibussowitsch     break;
5130d71ae5a4SJacob Faibussowitsch   case 1:
5131d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
5132d71ae5a4SJacob Faibussowitsch     break;
5133552f7358SJed Brown   case 2:
5134552f7358SJed Brown     switch (numCorners) {
513519436ca2SJed Brown     case 3:                 /* triangle */
513619436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5137552f7358SJed Brown       break;
513819436ca2SJed Brown     case 4:                 /* quadrilateral */
513919436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5140552f7358SJed Brown       break;
514119436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
514219436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5143552f7358SJed Brown       break;
514419436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
514519436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5146552f7358SJed Brown       break;
5147d71ae5a4SJacob Faibussowitsch     default:
5148d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5149552f7358SJed Brown     }
5150552f7358SJed Brown     break;
5151552f7358SJed Brown   case 3:
5152552f7358SJed Brown     switch (numCorners) {
515319436ca2SJed Brown     case 4:                 /* tetradehdron */
515419436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
5155552f7358SJed Brown       break;
515619436ca2SJed Brown     case 6:                 /* tet cohesive cells */
515719436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5158552f7358SJed Brown       break;
515919436ca2SJed Brown     case 8:                 /* hexahedron */
516019436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5161552f7358SJed Brown       break;
516219436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
516319436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5164552f7358SJed Brown       break;
516519436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
516619436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5167552f7358SJed Brown       break;
516819436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
516919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5170552f7358SJed Brown       break;
517119436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
517219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5173552f7358SJed Brown       break;
517419436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
517519436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
5176552f7358SJed Brown       break;
5177d71ae5a4SJacob Faibussowitsch     default:
5178d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5179552f7358SJed Brown     }
5180552f7358SJed Brown     break;
5181d71ae5a4SJacob Faibussowitsch   default:
5182d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
5183552f7358SJed Brown   }
51843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5185552f7358SJed Brown }
5186552f7358SJed Brown 
5187552f7358SJed Brown /*@
5188a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
5189552f7358SJed Brown 
5190552f7358SJed Brown   Not Collective
5191552f7358SJed Brown 
5192aa50250dSMatthew G. Knepley   Input Parameter:
5193a1cb98faSBarry Smith . dm - The `DMPLEX` object
5194552f7358SJed Brown 
5195aa50250dSMatthew G. Knepley   Output Parameter:
5196a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
5197552f7358SJed Brown 
5198552f7358SJed Brown   Level: developer
5199552f7358SJed Brown 
52001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
5201aa50250dSMatthew G. Knepley @*/
5202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
5203d71ae5a4SJacob Faibussowitsch {
5204aa50250dSMatthew G. Knepley   PetscFunctionBegin;
5205aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52064f572ea9SToby Isaac   PetscAssertPointer(depthLabel, 2);
5207c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
52083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5209aa50250dSMatthew G. Knepley }
5210aa50250dSMatthew G. Knepley 
5211aa50250dSMatthew G. Knepley /*@
5212aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
5213aa50250dSMatthew G. Knepley 
5214aa50250dSMatthew G. Knepley   Not Collective
5215aa50250dSMatthew G. Knepley 
5216aa50250dSMatthew G. Knepley   Input Parameter:
5217a1cb98faSBarry Smith . dm - The `DMPLEX` object
5218aa50250dSMatthew G. Knepley 
5219aa50250dSMatthew G. Knepley   Output Parameter:
5220aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
5221aa50250dSMatthew G. Knepley 
5222aa50250dSMatthew G. Knepley   Level: developer
5223552f7358SJed Brown 
5224b1bb481bSMatthew Knepley   Notes:
5225a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
5226a1cb98faSBarry Smith 
5227a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
5228a1cb98faSBarry Smith 
5229dc287ab2SVaclav Hapla   An empty mesh gives -1.
5230b1bb481bSMatthew Knepley 
52311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
5232552f7358SJed Brown @*/
5233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
5234d71ae5a4SJacob Faibussowitsch {
52359f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5236aa50250dSMatthew G. Knepley   DMLabel  label;
5237aa50250dSMatthew G. Knepley   PetscInt d = 0;
5238552f7358SJed Brown 
5239552f7358SJed Brown   PetscFunctionBegin;
5240552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52414f572ea9SToby Isaac   PetscAssertPointer(depth, 2);
52429f4ada15SMatthew G. Knepley   if (mesh->tr) {
52439f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
52449f4ada15SMatthew G. Knepley   } else {
52459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
52469566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
5247552f7358SJed Brown     *depth = d - 1;
52489f4ada15SMatthew G. Knepley   }
52493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5250552f7358SJed Brown }
5251552f7358SJed Brown 
5252552f7358SJed Brown /*@
525320f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
5254552f7358SJed Brown 
5255552f7358SJed Brown   Not Collective
5256552f7358SJed Brown 
5257552f7358SJed Brown   Input Parameters:
5258a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5259570fa34dSVaclav Hapla - depth - The requested depth
5260552f7358SJed Brown 
5261552f7358SJed Brown   Output Parameters:
526220f4b53cSBarry Smith + start - The first point at this `depth`
526320f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
5264552f7358SJed Brown 
5265552f7358SJed Brown   Level: developer
5266552f7358SJed Brown 
5267a1cb98faSBarry Smith   Notes:
5268a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
5269a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
5270a1cb98faSBarry Smith   higher dimension, e.g., "edges".
5271a1cb98faSBarry Smith 
52722827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
5273552f7358SJed Brown @*/
5274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
5275d71ae5a4SJacob Faibussowitsch {
52769f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5277aa50250dSMatthew G. Knepley   DMLabel  label;
527863d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
5279552f7358SJed Brown 
5280552f7358SJed Brown   PetscFunctionBegin;
5281552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52829371c9d4SSatish Balay   if (start) {
52834f572ea9SToby Isaac     PetscAssertPointer(start, 3);
52849371c9d4SSatish Balay     *start = 0;
52859371c9d4SSatish Balay   }
52869371c9d4SSatish Balay   if (end) {
52874f572ea9SToby Isaac     PetscAssertPointer(end, 4);
52889371c9d4SSatish Balay     *end = 0;
52899371c9d4SSatish Balay   }
52909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
52913ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5292570fa34dSVaclav Hapla   if (depth < 0) {
529363d1a920SMatthew G. Knepley     if (start) *start = pStart;
529463d1a920SMatthew G. Knepley     if (end) *end = pEnd;
52953ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5296552f7358SJed Brown   }
52979f4ada15SMatthew G. Knepley   if (mesh->tr) {
52989f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
52999f4ada15SMatthew G. Knepley   } else {
53009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
530128b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5302570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
53039f4ada15SMatthew G. Knepley   }
53043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5305552f7358SJed Brown }
5306552f7358SJed Brown 
5307552f7358SJed Brown /*@
530820f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5309552f7358SJed Brown 
5310552f7358SJed Brown   Not Collective
5311552f7358SJed Brown 
5312552f7358SJed Brown   Input Parameters:
5313a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5314570fa34dSVaclav Hapla - height - The requested height
5315552f7358SJed Brown 
5316552f7358SJed Brown   Output Parameters:
531720f4b53cSBarry Smith + start - The first point at this `height`
531820f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5319552f7358SJed Brown 
5320552f7358SJed Brown   Level: developer
5321552f7358SJed Brown 
5322a1cb98faSBarry Smith   Notes:
5323a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5324a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5325a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5326a1cb98faSBarry Smith 
53272827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5328552f7358SJed Brown @*/
5329d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5330d71ae5a4SJacob Faibussowitsch {
5331aa50250dSMatthew G. Knepley   DMLabel  label;
533263d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5333552f7358SJed Brown 
5334552f7358SJed Brown   PetscFunctionBegin;
5335552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53369371c9d4SSatish Balay   if (start) {
53374f572ea9SToby Isaac     PetscAssertPointer(start, 3);
53389371c9d4SSatish Balay     *start = 0;
53399371c9d4SSatish Balay   }
53409371c9d4SSatish Balay   if (end) {
53414f572ea9SToby Isaac     PetscAssertPointer(end, 4);
53429371c9d4SSatish Balay     *end = 0;
53439371c9d4SSatish Balay   }
53449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
53453ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5346570fa34dSVaclav Hapla   if (height < 0) {
534763d1a920SMatthew G. Knepley     if (start) *start = pStart;
534863d1a920SMatthew G. Knepley     if (end) *end = pEnd;
53493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5350552f7358SJed Brown   }
53519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
535259e4dc13SStefano Zampini   if (label) PetscCall(DMLabelGetNumValues(label, &depth));
535359e4dc13SStefano Zampini   else PetscCall(DMGetDimension(dm, &depth));
535459e4dc13SStefano Zampini   PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed");
535559e4dc13SStefano Zampini   PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end));
53563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5357552f7358SJed Brown }
5358552f7358SJed Brown 
5359ba2698f1SMatthew G. Knepley /*@
536020f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5361ba2698f1SMatthew G. Knepley 
5362ba2698f1SMatthew G. Knepley   Not Collective
5363ba2698f1SMatthew G. Knepley 
5364d8d19677SJose E. Roman   Input Parameters:
5365a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5366ba2698f1SMatthew G. Knepley - point - The point
5367ba2698f1SMatthew G. Knepley 
5368ba2698f1SMatthew G. Knepley   Output Parameter:
536920f4b53cSBarry Smith . depth - The depth of the `point`
5370ba2698f1SMatthew G. Knepley 
5371ba2698f1SMatthew G. Knepley   Level: intermediate
5372ba2698f1SMatthew G. Knepley 
53731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5374ba2698f1SMatthew G. Knepley @*/
5375d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5376d71ae5a4SJacob Faibussowitsch {
5377ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5378ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53794f572ea9SToby Isaac   PetscAssertPointer(depth, 3);
53809566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
53813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5382ba2698f1SMatthew G. Knepley }
5383ba2698f1SMatthew G. Knepley 
5384ba2698f1SMatthew G. Knepley /*@
538520f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
53860c0a32dcSVaclav Hapla 
53870c0a32dcSVaclav Hapla   Not Collective
53880c0a32dcSVaclav Hapla 
5389d8d19677SJose E. Roman   Input Parameters:
5390a1cb98faSBarry Smith + dm    - The `DMPLEX` object
53910c0a32dcSVaclav Hapla - point - The point
53920c0a32dcSVaclav Hapla 
53930c0a32dcSVaclav Hapla   Output Parameter:
539420f4b53cSBarry Smith . height - The height of the `point`
53950c0a32dcSVaclav Hapla 
53960c0a32dcSVaclav Hapla   Level: intermediate
53970c0a32dcSVaclav Hapla 
53981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
53990c0a32dcSVaclav Hapla @*/
5400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5401d71ae5a4SJacob Faibussowitsch {
54020c0a32dcSVaclav Hapla   PetscInt n, pDepth;
54030c0a32dcSVaclav Hapla 
54040c0a32dcSVaclav Hapla   PetscFunctionBegin;
54050c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54064f572ea9SToby Isaac   PetscAssertPointer(height, 3);
54079566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
54089566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
54090c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
54103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54110c0a32dcSVaclav Hapla }
54120c0a32dcSVaclav Hapla 
54130c0a32dcSVaclav Hapla /*@
5414a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5415ba2698f1SMatthew G. Knepley 
5416ba2698f1SMatthew G. Knepley   Not Collective
5417ba2698f1SMatthew G. Knepley 
5418ba2698f1SMatthew G. Knepley   Input Parameter:
5419a1cb98faSBarry Smith . dm - The `DMPLEX` object
5420ba2698f1SMatthew G. Knepley 
5421ba2698f1SMatthew G. Knepley   Output Parameter:
5422a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5423412e9a14SMatthew G. Knepley 
5424ba2698f1SMatthew G. Knepley   Level: developer
5425ba2698f1SMatthew G. Knepley 
5426a1cb98faSBarry Smith   Note:
5427a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5428a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5429a1cb98faSBarry Smith 
54301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5431ba2698f1SMatthew G. Knepley @*/
5432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5433d71ae5a4SJacob Faibussowitsch {
5434ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5435ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54364f572ea9SToby Isaac   PetscAssertPointer(celltypeLabel, 2);
54379566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5438ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
54393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5440ba2698f1SMatthew G. Knepley }
5441ba2698f1SMatthew G. Knepley 
5442ba2698f1SMatthew G. Knepley /*@
5443ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5444ba2698f1SMatthew G. Knepley 
5445ba2698f1SMatthew G. Knepley   Not Collective
5446ba2698f1SMatthew G. Knepley 
5447d8d19677SJose E. Roman   Input Parameters:
5448a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5449ba2698f1SMatthew G. Knepley - cell - The cell
5450ba2698f1SMatthew G. Knepley 
5451ba2698f1SMatthew G. Knepley   Output Parameter:
5452ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5453ba2698f1SMatthew G. Knepley 
5454ba2698f1SMatthew G. Knepley   Level: intermediate
5455ba2698f1SMatthew G. Knepley 
54561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5457ba2698f1SMatthew G. Knepley @*/
5458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5459d71ae5a4SJacob Faibussowitsch {
54609f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5461ba2698f1SMatthew G. Knepley   DMLabel  label;
5462ba2698f1SMatthew G. Knepley   PetscInt ct;
5463ba2698f1SMatthew G. Knepley 
5464ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5465ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54664f572ea9SToby Isaac   PetscAssertPointer(celltype, 3);
54679f4ada15SMatthew G. Knepley   if (mesh->tr) {
54689f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
54699f4ada15SMatthew G. Knepley   } else {
547021027e53SStefano Zampini     PetscInt pStart, pEnd;
547121027e53SStefano Zampini 
547221027e53SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL));
547321027e53SStefano Zampini     if (!mesh->cellTypes) { /* XXX remove? optimize? */
547421027e53SStefano Zampini       PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd));
547521027e53SStefano Zampini       PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
547621027e53SStefano Zampini       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
547721027e53SStefano Zampini       for (PetscInt p = pStart; p < pEnd; p++) {
547821027e53SStefano Zampini         PetscCall(DMLabelGetValue(label, p, &ct));
547921027e53SStefano Zampini         mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct;
548021027e53SStefano Zampini       }
548121027e53SStefano Zampini     }
548221027e53SStefano Zampini     *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8;
548321027e53SStefano Zampini     if (PetscDefined(USE_DEBUG)) {
54849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
54859566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, cell, &ct));
548663a3b9bcSJacob Faibussowitsch       PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5487936381afSPierre Jolivet       PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct);
548821027e53SStefano Zampini     }
54899f4ada15SMatthew G. Knepley   }
54903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5491ba2698f1SMatthew G. Knepley }
5492ba2698f1SMatthew G. Knepley 
5493412e9a14SMatthew G. Knepley /*@
5494412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5495412e9a14SMatthew G. Knepley 
5496412e9a14SMatthew G. Knepley   Not Collective
5497412e9a14SMatthew G. Knepley 
5498412e9a14SMatthew G. Knepley   Input Parameters:
5499a1cb98faSBarry Smith + dm       - The `DMPLEX` object
5500412e9a14SMatthew G. Knepley . cell     - The cell
5501412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5502412e9a14SMatthew G. Knepley 
5503a1cb98faSBarry Smith   Level: advanced
5504a1cb98faSBarry Smith 
5505a1cb98faSBarry Smith   Note:
5506a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5507412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5508412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5509db485b19SStefano Zampini   DMCreateLabel(dm, "celltype") before getting or setting any cell types.
5510412e9a14SMatthew G. Knepley 
55111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5512412e9a14SMatthew G. Knepley @*/
5513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5514d71ae5a4SJacob Faibussowitsch {
551521027e53SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
5516412e9a14SMatthew G. Knepley   DMLabel  label;
551721027e53SStefano Zampini   PetscInt pStart, pEnd;
5518412e9a14SMatthew G. Knepley 
5519412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5520412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
552121027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
55229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
55239566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
552421027e53SStefano Zampini   if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
552521027e53SStefano Zampini   mesh->cellTypes[cell - pStart].value_as_uint8 = celltype;
55263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5527412e9a14SMatthew G. Knepley }
5528412e9a14SMatthew G. Knepley 
5529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5530d71ae5a4SJacob Faibussowitsch {
5531c789d87fSToby Isaac   PetscSection section;
55323e922f36SToby Isaac   PetscInt     maxHeight;
5533dd4c3f67SMatthew G. Knepley   const char  *prefix;
5534552f7358SJed Brown 
5535552f7358SJed Brown   PetscFunctionBegin;
55369566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5537dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5538dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5539dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
55409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
55419566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
55429566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
55439566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
55449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
55458f4c458bSMatthew G. Knepley 
55469566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
55479566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5548dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5549dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
55503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5551552f7358SJed Brown }
5552552f7358SJed Brown 
5553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5554d71ae5a4SJacob Faibussowitsch {
55556858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
55566858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5557f19dbd58SToby Isaac 
5558f19dbd58SToby Isaac   PetscFunctionBegin;
5559f19dbd58SToby Isaac   *field = NULL;
55609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
55619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
55626858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
55636858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5564f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
55656858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
55666858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5567f19dbd58SToby Isaac   }
55683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5569f19dbd58SToby Isaac }
5570f19dbd58SToby Isaac 
55717cd05799SMatthew G. Knepley /*@C
55727cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
55737cd05799SMatthew G. Knepley 
55747cd05799SMatthew G. Knepley   Not Collective
55757cd05799SMatthew G. Knepley 
55762fe279fdSBarry Smith   Input Parameter:
5577a1cb98faSBarry Smith . dm - The `DMPLEX` object
55787cd05799SMatthew G. Knepley 
55797cd05799SMatthew G. Knepley   Output Parameter:
5580a1cb98faSBarry Smith . section - The `PetscSection` object
55817cd05799SMatthew G. Knepley 
55827cd05799SMatthew G. Knepley   Level: developer
55837cd05799SMatthew G. Knepley 
55841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
55857cd05799SMatthew G. Knepley @*/
5586d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5587d71ae5a4SJacob Faibussowitsch {
5588552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5589552f7358SJed Brown 
5590552f7358SJed Brown   PetscFunctionBegin;
5591552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5592552f7358SJed Brown   if (section) *section = mesh->coneSection;
55933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5594552f7358SJed Brown }
5595552f7358SJed Brown 
55967cd05799SMatthew G. Knepley /*@C
55977cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
55987cd05799SMatthew G. Knepley 
55997cd05799SMatthew G. Knepley   Not Collective
56007cd05799SMatthew G. Knepley 
56012fe279fdSBarry Smith   Input Parameter:
5602a1cb98faSBarry Smith . dm - The `DMPLEX` object
56037cd05799SMatthew G. Knepley 
56047cd05799SMatthew G. Knepley   Output Parameter:
5605a1cb98faSBarry Smith . section - The `PetscSection` object
56067cd05799SMatthew G. Knepley 
56077cd05799SMatthew G. Knepley   Level: developer
56087cd05799SMatthew G. Knepley 
56091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
56107cd05799SMatthew G. Knepley @*/
5611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5612d71ae5a4SJacob Faibussowitsch {
56138cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
56148cb4d582SMatthew G. Knepley 
56158cb4d582SMatthew G. Knepley   PetscFunctionBegin;
56168cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56178cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
56183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56198cb4d582SMatthew G. Knepley }
56208cb4d582SMatthew G. Knepley 
56217cd05799SMatthew G. Knepley /*@C
56227cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
56237cd05799SMatthew G. Knepley 
56247cd05799SMatthew G. Knepley   Not Collective
56257cd05799SMatthew G. Knepley 
56262fe279fdSBarry Smith   Input Parameter:
5627a1cb98faSBarry Smith . dm - The `DMPLEX` object
56287cd05799SMatthew G. Knepley 
56297cd05799SMatthew G. Knepley   Output Parameter:
56307cd05799SMatthew G. Knepley . cones - The cone for each point
56317cd05799SMatthew G. Knepley 
56327cd05799SMatthew G. Knepley   Level: developer
56337cd05799SMatthew G. Knepley 
56341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
56357cd05799SMatthew G. Knepley @*/
5636d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5637d71ae5a4SJacob Faibussowitsch {
5638552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5639552f7358SJed Brown 
5640552f7358SJed Brown   PetscFunctionBegin;
5641552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5642552f7358SJed Brown   if (cones) *cones = mesh->cones;
56433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5644552f7358SJed Brown }
5645552f7358SJed Brown 
56467cd05799SMatthew G. Knepley /*@C
56477cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
56487cd05799SMatthew G. Knepley 
56497cd05799SMatthew G. Knepley   Not Collective
56507cd05799SMatthew G. Knepley 
56512fe279fdSBarry Smith   Input Parameter:
5652a1cb98faSBarry Smith . dm - The `DMPLEX` object
56537cd05799SMatthew G. Knepley 
56547cd05799SMatthew G. Knepley   Output Parameter:
5655b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
56567cd05799SMatthew G. Knepley 
56577cd05799SMatthew G. Knepley   Level: developer
56587cd05799SMatthew G. Knepley 
5659b5a892a1SMatthew G. Knepley   Notes:
5660a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5661b5a892a1SMatthew G. Knepley 
5662a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5663b5a892a1SMatthew G. Knepley 
56641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
56657cd05799SMatthew G. Knepley @*/
5666d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5667d71ae5a4SJacob Faibussowitsch {
5668552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5669552f7358SJed Brown 
5670552f7358SJed Brown   PetscFunctionBegin;
5671552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5672552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
56733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5674552f7358SJed Brown }
5675552f7358SJed Brown 
5676552f7358SJed Brown /******************************** FEM Support **********************************/
5677552f7358SJed Brown 
5678d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
5679d2b2dc1eSMatthew G. Knepley {
5680d2b2dc1eSMatthew G. Knepley   PetscInt depth;
5681d2b2dc1eSMatthew G. Knepley 
5682d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
5683d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
5684d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS));
5685d2b2dc1eSMatthew G. Knepley   if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS));
5686d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5687d2b2dc1eSMatthew G. Knepley }
5688d2b2dc1eSMatthew G. Knepley 
56895962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS)
56905962854dSMatthew G. Knepley {
56915962854dSMatthew G. Knepley   PetscInt depth;
56925962854dSMatthew G. Knepley 
56935962854dSMatthew G. Knepley   PetscFunctionBegin;
56945962854dSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
56955962854dSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS));
56965962854dSMatthew G. Knepley   if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS));
56975962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
56985962854dSMatthew G. Knepley }
56995962854dSMatthew G. Knepley 
57009e8305c2SJed Brown /*
57019e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
57029e8305c2SJed Brown  representing a line in the section.
57039e8305c2SJed Brown */
57045f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor)
5705d71ae5a4SJacob Faibussowitsch {
5706e327e467SRezgar Shakeri   PetscObject  obj;
5707e327e467SRezgar Shakeri   PetscClassId id;
5708e327e467SRezgar Shakeri   PetscFE      fe = NULL;
5709e327e467SRezgar Shakeri 
57109e8305c2SJed Brown   PetscFunctionBeginHot;
57119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5712e327e467SRezgar Shakeri   PetscCall(DMGetField(dm, field, NULL, &obj));
5713e327e467SRezgar Shakeri   PetscCall(PetscObjectGetClassId(obj, &id));
5714e327e467SRezgar Shakeri   if (id == PETSCFE_CLASSID) fe = (PetscFE)obj;
5715e327e467SRezgar Shakeri 
5716e327e467SRezgar Shakeri   if (!fe) {
5717e327e467SRezgar Shakeri     /* Assume the full interpolated mesh is in the chart; lines in particular */
57189e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
57199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
57209e8305c2SJed Brown     *k = *k / *Nc + 1;
5721e327e467SRezgar Shakeri   } else {
5722e327e467SRezgar Shakeri     PetscInt       dual_space_size, dim;
57235f82726aSMatthew G. Knepley     PetscDualSpace dsp;
57245f82726aSMatthew G. Knepley 
5725e327e467SRezgar Shakeri     PetscCall(DMGetDimension(dm, &dim));
57265f82726aSMatthew G. Knepley     PetscCall(PetscFEGetDualSpace(fe, &dsp));
57275f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size));
5728e327e467SRezgar Shakeri     *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1;
57295f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous));
57305f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor));
57315f82726aSMatthew G. Knepley   }
57325f82726aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
57335f82726aSMatthew G. Knepley }
57345f82726aSMatthew G. Knepley 
57355f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof)
57365f82726aSMatthew G. Knepley {
57375f82726aSMatthew G. Knepley   PetscFunctionBeginHot;
57385f82726aSMatthew G. Knepley   if (tensor) {
57395f82726aSMatthew G. Knepley     *dof = PetscPowInt(k + 1, dim);
57405f82726aSMatthew G. Knepley   } else {
57415f82726aSMatthew G. Knepley     switch (dim) {
57425f82726aSMatthew G. Knepley     case 1:
57435f82726aSMatthew G. Knepley       *dof = k + 1;
57445f82726aSMatthew G. Knepley       break;
57455f82726aSMatthew G. Knepley     case 2:
57465f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2)) / 2;
57475f82726aSMatthew G. Knepley       break;
57485f82726aSMatthew G. Knepley     case 3:
57495f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2) * (k + 3)) / 6;
57505f82726aSMatthew G. Knepley       break;
57515f82726aSMatthew G. Knepley     default:
57525f82726aSMatthew G. Knepley       *dof = 0;
57535f82726aSMatthew G. Knepley     }
57549e8305c2SJed Brown   }
57553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57569e8305c2SJed Brown }
57579e8305c2SJed Brown 
5758a4355906SMatthew Knepley /*@
5759bc1eb3faSJed Brown 
5760bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5761bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
576220f4b53cSBarry Smith   section provided (or the section of the `DM`).
5763a4355906SMatthew Knepley 
5764a4355906SMatthew Knepley   Input Parameters:
576520f4b53cSBarry Smith + dm      - The `DM`
576620f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
576720f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5768a4355906SMatthew Knepley 
5769bc1eb3faSJed Brown   Example:
5770bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5771bc1eb3faSJed Brown .vb
5772bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5773bc1eb3faSJed Brown 
5774bc1eb3faSJed Brown   v4 -- e6 -- v3
5775bc1eb3faSJed Brown   |           |
5776bc1eb3faSJed Brown   e7    c0    e8
5777bc1eb3faSJed Brown   |           |
5778bc1eb3faSJed Brown   v1 -- e5 -- v2
5779bc1eb3faSJed Brown .ve
5780bc1eb3faSJed Brown 
5781bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5782bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5783bc1eb3faSJed Brown .vb
5784bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5785bc1eb3faSJed Brown     v1 -> [4]
5786bc1eb3faSJed Brown     ...
5787bc1eb3faSJed Brown     e5 -> [8, 9]
5788bc1eb3faSJed Brown .ve
5789bc1eb3faSJed Brown 
5790bc1eb3faSJed Brown   which corresponds to the dofs
5791bc1eb3faSJed Brown .vb
5792bc1eb3faSJed Brown     6   10  11  7
5793bc1eb3faSJed Brown     13  2   3   15
5794bc1eb3faSJed Brown     12  0   1   14
5795bc1eb3faSJed Brown     4   8   9   5
5796bc1eb3faSJed Brown .ve
5797bc1eb3faSJed Brown 
5798bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5799bc1eb3faSJed Brown .vb
5800bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5801bc1eb3faSJed Brown .ve
5802bc1eb3faSJed Brown 
5803bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5804bc1eb3faSJed Brown .vb
5805bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5806bc1eb3faSJed Brown .ve
5807bc1eb3faSJed Brown 
5808a4355906SMatthew Knepley   Level: developer
5809a4355906SMatthew Knepley 
5810da9ac489SAlbert Cowie   Notes:
5811a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5812a1cb98faSBarry Smith   degree of the basis.
5813a1cb98faSBarry Smith 
5814da9ac489SAlbert Cowie   This is required to run with libCEED.
5815da9ac489SAlbert Cowie 
58161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5817a4355906SMatthew Knepley @*/
5818d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5819d71ae5a4SJacob Faibussowitsch {
58207391a63aSMatthew G. Knepley   DMLabel   label;
5821bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
58225f82726aSMatthew G. Knepley   PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE;
58233194fc30SMatthew G. Knepley 
58243194fc30SMatthew G. Knepley   PetscFunctionBegin;
58259566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
58263ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5827a433471fSStefano Zampini   if (point < 0) {
5828a433471fSStefano Zampini     PetscInt sStart, sEnd;
5829a433471fSStefano Zampini 
58309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5831a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5832a433471fSStefano Zampini   }
58339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
58349566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
58359566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58369371c9d4SSatish Balay   if (depth == 1) {
58379371c9d4SSatish Balay     eStart = point;
58389371c9d4SSatish Balay   } else if (depth == dim) {
58397391a63aSMatthew G. Knepley     const PetscInt *cone;
58407391a63aSMatthew G. Knepley 
58419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5842d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5843d4e6627bSStefano Zampini     else if (dim == 3) {
5844d4e6627bSStefano Zampini       const PetscInt *cone2;
58459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5846d4e6627bSStefano Zampini       eStart = cone2[0];
584763a3b9bcSJacob 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);
584863a3b9bcSJacob 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);
5849e327e467SRezgar Shakeri 
58509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5851bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5852bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5853bb197d40SJed Brown     PetscInt *perm;
5854bb197d40SJed Brown 
58553194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
58565f82726aSMatthew G. Knepley       PetscInt dof;
58575f82726aSMatthew G. Knepley 
58585f82726aSMatthew G. Knepley       PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58595f82726aSMatthew 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);
58605f82726aSMatthew G. Knepley       if (!continuous && d < dim) continue;
58615f82726aSMatthew G. Knepley       PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58625f82726aSMatthew G. Knepley       size += dof * Nc;
58633194fc30SMatthew G. Knepley     }
58649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
58653194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5866bb197d40SJed Brown       switch (d) {
5867babf31e0SJed Brown       case 1:
58685f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58695f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
5870babf31e0SJed Brown         /*
5871babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5872babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5873babf31e0SJed Brown          */
5874e327e467SRezgar Shakeri         if (continuous) {
5875babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
58769371c9d4SSatish Balay           for (i = 0; i < k - 1; i++)
58779371c9d4SSatish Balay             for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5878babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5879babf31e0SJed Brown           foffset = offset;
5880e327e467SRezgar Shakeri         } else {
58815f82726aSMatthew G. Knepley           PetscInt dof;
58825f82726aSMatthew G. Knepley 
58835f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58845f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
58855f82726aSMatthew G. Knepley           foffset = offset;
5886e327e467SRezgar Shakeri         }
5887babf31e0SJed Brown         break;
588889eabcffSMatthew G. Knepley       case 2:
58893194fc30SMatthew 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} */
58905f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58915f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
58923194fc30SMatthew G. Knepley         /* The SEM order is
58933194fc30SMatthew G. Knepley 
58943194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
589589eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
58963194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
58973194fc30SMatthew G. Knepley          */
5898e327e467SRezgar Shakeri         if (continuous) {
58993194fc30SMatthew G. Knepley           const PetscInt of   = 0;
59003194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
59013194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
59023194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
59033194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
59043194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
59053194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
59063194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
59073194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
59083194fc30SMatthew G. Knepley           PetscInt       o;
59093194fc30SMatthew G. Knepley 
59103194fc30SMatthew G. Knepley           /* bottom */
59113194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
59129371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
59139371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59143194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
59153194fc30SMatthew G. Knepley           /* middle */
59163194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
59173194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
59189371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
59199371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59203194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
59213194fc30SMatthew G. Knepley           }
59223194fc30SMatthew G. Knepley           /* top */
59233194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
59249371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
59259371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59263194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
59273194fc30SMatthew G. Knepley           foffset = offset;
5928e327e467SRezgar Shakeri         } else {
59295f82726aSMatthew G. Knepley           PetscInt dof;
59305f82726aSMatthew G. Knepley 
59315f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
59325f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
59335f82726aSMatthew G. Knepley           foffset = offset;
59343194fc30SMatthew G. Knepley         }
593589eabcffSMatthew G. Knepley         break;
593689eabcffSMatthew G. Knepley       case 3:
593789eabcffSMatthew G. Knepley         /* The original hex closure is
593889eabcffSMatthew G. Knepley 
593989eabcffSMatthew G. Knepley          {c,
594089eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
594189eabcffSMatthew 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,
594289eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
594389eabcffSMatthew G. Knepley          */
59445f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
59455f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
594689eabcffSMatthew G. Knepley         /* The SEM order is
594789eabcffSMatthew G. Knepley          Bottom Slice
594889eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
594989eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
595089eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
595189eabcffSMatthew G. Knepley 
595289eabcffSMatthew G. Knepley          Middle Slice (j)
595389eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
595489eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
595589eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
595689eabcffSMatthew G. Knepley 
595789eabcffSMatthew G. Knepley          Top Slice
595889eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
595989eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
596089eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
596189eabcffSMatthew G. Knepley          */
5962e327e467SRezgar Shakeri         if (continuous) {
596389eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
596489eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
596589eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
596689eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
596789eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
596889eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
596989eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
597089eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
597189eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
597289eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
597389eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
597489eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
597589eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
597689eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
597789eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
597889eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
597989eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
598089eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
598189eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
598289eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
598389eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
598489eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
598589eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
598689eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
598789eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
598889eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
598989eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
599089eabcffSMatthew G. Knepley           PetscInt       o, n;
599189eabcffSMatthew G. Knepley 
599289eabcffSMatthew G. Knepley           /* Bottom Slice */
599389eabcffSMatthew G. Knepley           /*   bottom */
599489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
59959371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
59969371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
599789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
599889eabcffSMatthew G. Knepley           /*   middle */
599989eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
600089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
60019371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
60029371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
60039371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
60049371c9d4SSatish Balay             }
600589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
60063194fc30SMatthew G. Knepley           }
600789eabcffSMatthew G. Knepley           /*   top */
600889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
60099371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
60109371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
601189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
601289eabcffSMatthew G. Knepley 
601389eabcffSMatthew G. Knepley           /* Middle Slice */
601489eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
601589eabcffSMatthew G. Knepley             /*   bottom */
601689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
60179371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
60189371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
601989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
602089eabcffSMatthew G. Knepley             /*   middle */
602189eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
602289eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
60239371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
60249371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
602589eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
602689eabcffSMatthew G. Knepley             }
602789eabcffSMatthew G. Knepley             /*   top */
602889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
60299371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
60309371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
603189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
603289eabcffSMatthew G. Knepley           }
603389eabcffSMatthew G. Knepley 
603489eabcffSMatthew G. Knepley           /* Top Slice */
603589eabcffSMatthew G. Knepley           /*   bottom */
603689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
60379371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
60389371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
603989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
604089eabcffSMatthew G. Knepley           /*   middle */
604189eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
604289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
60439371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
60449371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
604589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
604689eabcffSMatthew G. Knepley           }
604789eabcffSMatthew G. Knepley           /*   top */
604889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
60499371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
60509371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
605189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
605289eabcffSMatthew G. Knepley 
605389eabcffSMatthew G. Knepley           foffset = offset;
6054e327e467SRezgar Shakeri         } else {
60555f82726aSMatthew G. Knepley           PetscInt dof;
60565f82726aSMatthew G. Knepley 
60575f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
60585f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
60595f82726aSMatthew G. Knepley           foffset = offset;
606089eabcffSMatthew G. Knepley         }
606189eabcffSMatthew G. Knepley         break;
6062d71ae5a4SJacob Faibussowitsch       default:
6063d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
606489eabcffSMatthew G. Knepley       }
606589eabcffSMatthew G. Knepley     }
606663a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
60673194fc30SMatthew G. Knepley     /* Check permutation */
60683194fc30SMatthew G. Knepley     {
60693194fc30SMatthew G. Knepley       PetscInt *check;
60703194fc30SMatthew G. Knepley 
60719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
60721dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
60731dca8a05SBarry Smith         check[i] = -1;
60741dca8a05SBarry 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]);
60751dca8a05SBarry Smith       }
60763194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
60771dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
60789566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
60793194fc30SMatthew G. Knepley     }
60809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
6081a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
6082a05c9aa3SJed Brown       PetscInt *loc_perm;
60839566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
6084a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
6085a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
6086a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
6087a05c9aa3SJed Brown       }
60889566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
6089a05c9aa3SJed Brown     }
6090bb197d40SJed Brown   }
60913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60923194fc30SMatthew G. Knepley }
60933194fc30SMatthew G. Knepley 
6094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
6095d71ae5a4SJacob Faibussowitsch {
6096e071409bSToby Isaac   PetscDS  prob;
6097e071409bSToby Isaac   PetscInt depth, Nf, h;
6098e071409bSToby Isaac   DMLabel  label;
6099e071409bSToby Isaac 
6100e071409bSToby Isaac   PetscFunctionBeginHot;
61019566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
6102e071409bSToby Isaac   Nf      = prob->Nf;
6103e071409bSToby Isaac   label   = dm->depthLabel;
6104e071409bSToby Isaac   *dspace = NULL;
6105e071409bSToby Isaac   if (field < Nf) {
6106e071409bSToby Isaac     PetscObject disc = prob->disc[field];
6107e071409bSToby Isaac 
6108e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
6109e071409bSToby Isaac       PetscDualSpace dsp;
6110e071409bSToby Isaac 
61119566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
61129566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
61139566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
6114e071409bSToby Isaac       h = depth - 1 - h;
6115e071409bSToby Isaac       if (h) {
61169566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
6117e071409bSToby Isaac       } else {
6118e071409bSToby Isaac         *dspace = dsp;
6119e071409bSToby Isaac       }
6120e071409bSToby Isaac     }
6121e071409bSToby Isaac   }
61223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6123e071409bSToby Isaac }
6124e071409bSToby Isaac 
6125d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6126d71ae5a4SJacob Faibussowitsch {
612728351e22SJed Brown   PetscScalar       *array;
612828351e22SJed Brown   const PetscScalar *vArray;
6129d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
61301a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
6131552f7358SJed Brown 
61321b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
61349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
61359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
61369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
61373f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
61389df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
61399df71ca4SMatthew G. Knepley       PetscInt dof;
6140d9917b9dSMatthew G. Knepley 
61419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
61429df71ca4SMatthew G. Knepley       size += dof;
61439df71ca4SMatthew G. Knepley     }
61449df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
61459df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
61462a3aaacfSMatthew G. Knepley       PetscInt       dof;
61475a1bb5cfSMatthew G. Knepley 
61485a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
61499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
61505a1bb5cfSMatthew G. Knepley       size += dof;
61515a1bb5cfSMatthew G. Knepley     }
61523f7cbbe7SMatthew G. Knepley     if (!values) {
61533f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
61543ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
61553f7cbbe7SMatthew G. Knepley     }
61569566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
6157982e9ed1SMatthew G. Knepley   } else {
6158982e9ed1SMatthew G. Knepley     array = *values;
6159982e9ed1SMatthew G. Knepley   }
61609df71ca4SMatthew G. Knepley   size = 0;
616128351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
61629df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
61639df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
616428351e22SJed Brown     const PetscScalar *varr;
6165d9917b9dSMatthew G. Knepley 
61669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
61679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
61688e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
6169ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61709df71ca4SMatthew G. Knepley     size += dof;
61719df71ca4SMatthew G. Knepley   }
61729df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
61739df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
61749df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
61755a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
617628351e22SJed Brown     const PetscScalar *varr;
61775a1bb5cfSMatthew G. Knepley 
617852ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
61799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
61809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
61818e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
61825a1bb5cfSMatthew G. Knepley     if (o >= 0) {
6183ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61845a1bb5cfSMatthew G. Knepley     } else {
6185ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
61865a1bb5cfSMatthew G. Knepley     }
61879df71ca4SMatthew G. Knepley     size += dof;
61885a1bb5cfSMatthew G. Knepley   }
618928351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
61909df71ca4SMatthew G. Knepley   if (!*values) {
61915a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
61925a1bb5cfSMatthew G. Knepley     *values = array;
61939df71ca4SMatthew G. Knepley   } else {
619463a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
61958c312ff3SMatthew G. Knepley     *csize = size;
61969df71ca4SMatthew G. Knepley   }
61973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61985a1bb5cfSMatthew G. Knepley }
6199d9917b9dSMatthew G. Knepley 
620027f02ce8SMatthew G. Knepley /* Compress out points not in the section */
6201d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
6202d71ae5a4SJacob Faibussowitsch {
620327f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
620427f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
620527f02ce8SMatthew G. Knepley 
62069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
620727f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
620827f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
620927f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
621027f02ce8SMatthew G. Knepley       points[q * 2]     = r;
621127f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
621227f02ce8SMatthew G. Knepley       ++q;
621327f02ce8SMatthew G. Knepley     }
621427f02ce8SMatthew G. Knepley   }
621527f02ce8SMatthew G. Knepley   *numPoints = q;
62163ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
621727f02ce8SMatthew G. Knepley }
621827f02ce8SMatthew G. Knepley 
621997529cf3SJed Brown /* Compressed closure does not apply closure permutation */
622007218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6221d71ae5a4SJacob Faibussowitsch {
622227f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
6223923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
6224923c78e0SToby Isaac 
6225923c78e0SToby Isaac   PetscFunctionBeginHot;
62269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
622707218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
6228923c78e0SToby Isaac     PetscInt dof, off;
6229923c78e0SToby Isaac 
62309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
62319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
62329566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
6233923c78e0SToby Isaac     np  = dof / 2;
62348e3a54c0SPierre Jolivet     pts = PetscSafePointerPlusOffset((PetscInt *)cla, off);
623527f02ce8SMatthew G. Knepley   } else {
623607218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
62379566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
6238923c78e0SToby Isaac   }
6239923c78e0SToby Isaac   *numPoints = np;
6240923c78e0SToby Isaac   *points    = pts;
6241923c78e0SToby Isaac   *clp       = cla;
62423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6243923c78e0SToby Isaac }
6244923c78e0SToby Isaac 
6245d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6246d71ae5a4SJacob Faibussowitsch {
6247923c78e0SToby Isaac   PetscFunctionBeginHot;
6248923c78e0SToby Isaac   if (!*clPoints) {
62499566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
6250923c78e0SToby Isaac   } else {
62519566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
6252923c78e0SToby Isaac   }
6253923c78e0SToby Isaac   *numPoints = 0;
6254923c78e0SToby Isaac   *points    = NULL;
6255923c78e0SToby Isaac   *clSec     = NULL;
6256923c78e0SToby Isaac   *clPoints  = NULL;
6257923c78e0SToby Isaac   *clp       = NULL;
62583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6259923c78e0SToby Isaac }
6260923c78e0SToby Isaac 
6261d71ae5a4SJacob 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[])
6262d71ae5a4SJacob Faibussowitsch {
62631a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
626497e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
626597e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
62661a271a75SMatthew G. Knepley 
62671a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6268fe02ba77SJed Brown   *size = 0;
62699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
627097e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
627197e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
627297e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
627397e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
62741a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
62751a271a75SMatthew G. Knepley     const PetscScalar *varr;
62761a271a75SMatthew G. Knepley 
62779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
62789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
62798e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
628097e99dd9SToby Isaac     if (clperm) {
628197e99dd9SToby Isaac       if (perm) {
628297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
62831a271a75SMatthew G. Knepley       } else {
628497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
628597e99dd9SToby Isaac       }
628697e99dd9SToby Isaac       if (flip) {
628797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
628897e99dd9SToby Isaac       }
628997e99dd9SToby Isaac     } else {
629097e99dd9SToby Isaac       if (perm) {
629197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
629297e99dd9SToby Isaac       } else {
629397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
629497e99dd9SToby Isaac       }
629597e99dd9SToby Isaac       if (flip) {
629697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
62971a271a75SMatthew G. Knepley       }
62981a271a75SMatthew G. Knepley     }
629997e99dd9SToby Isaac     offset += dof;
630097e99dd9SToby Isaac   }
63019566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
63021a271a75SMatthew G. Knepley   *size = offset;
63033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63041a271a75SMatthew G. Knepley }
63051a271a75SMatthew G. Knepley 
6306d71ae5a4SJacob 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[])
6307d71ae5a4SJacob Faibussowitsch {
63081a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
63091a271a75SMatthew G. Knepley 
63101a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6311fe02ba77SJed Brown   *size = 0;
63121a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
631397e99dd9SToby Isaac     PetscInt            p;
631497e99dd9SToby Isaac     const PetscInt    **perms = NULL;
631597e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63161a271a75SMatthew G. Knepley 
63179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
631897e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
631997e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
632097e99dd9SToby Isaac       PetscInt           fdof, foff, b;
63211a271a75SMatthew G. Knepley       const PetscScalar *varr;
632297e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
632397e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
63241a271a75SMatthew G. Knepley 
63259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63271a271a75SMatthew G. Knepley       varr = &vArray[foff];
632897e99dd9SToby Isaac       if (clperm) {
63299371c9d4SSatish Balay         if (perm) {
6330ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
63311a271a75SMatthew G. Knepley         } else {
6332ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
63339371c9d4SSatish Balay         }
63349371c9d4SSatish Balay         if (flip) {
6335ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
63369371c9d4SSatish Balay         }
63379371c9d4SSatish Balay       } else {
63389371c9d4SSatish Balay         if (perm) {
6339ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
63409371c9d4SSatish Balay         } else {
6341ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
63429371c9d4SSatish Balay         }
63439371c9d4SSatish Balay         if (flip) {
6344ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
63459371c9d4SSatish Balay         }
63461a271a75SMatthew G. Knepley       }
634797e99dd9SToby Isaac       offset += fdof;
63481a271a75SMatthew G. Knepley     }
63499566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
63501a271a75SMatthew G. Knepley   }
63511a271a75SMatthew G. Knepley   *size = offset;
63523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63531a271a75SMatthew G. Knepley }
63541a271a75SMatthew G. Knepley 
6355e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
635607218a29SMatthew G. Knepley {
635707218a29SMatthew G. Knepley   PetscSection    clSection;
635807218a29SMatthew G. Knepley   IS              clPoints;
635907218a29SMatthew G. Knepley   PetscInt       *points = NULL;
6360e8e188d2SZach Atkins   const PetscInt *clp, *perm = NULL;
636107218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
636207218a29SMatthew G. Knepley 
636307218a29SMatthew G. Knepley   PetscFunctionBeginHot;
636407218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
636507218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
636607218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6367e8e188d2SZach Atkins   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
636807218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
636907218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
637007218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
637107218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
637207218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
637307218a29SMatthew G. Knepley   }
637407218a29SMatthew G. Knepley   /* Get points */
637507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
637607218a29SMatthew G. Knepley   /* Get sizes */
637707218a29SMatthew G. Knepley   asize = 0;
637807218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
637907218a29SMatthew G. Knepley     PetscInt dof;
638007218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
638107218a29SMatthew G. Knepley     asize += dof;
638207218a29SMatthew G. Knepley   }
638307218a29SMatthew G. Knepley   if (values) {
638407218a29SMatthew G. Knepley     const PetscScalar *vArray;
638507218a29SMatthew G. Knepley     PetscInt           size;
638607218a29SMatthew G. Knepley 
638707218a29SMatthew G. Knepley     if (*values) {
638807218a29SMatthew 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);
638907218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
6390e8e188d2SZach Atkins     if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
639107218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
639207218a29SMatthew G. Knepley     /* Get values */
639307218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
639407218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
639507218a29SMatthew 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);
639607218a29SMatthew G. Knepley     /* Cleanup array */
639707218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
639807218a29SMatthew G. Knepley   }
639907218a29SMatthew G. Knepley   if (csize) *csize = asize;
640007218a29SMatthew G. Knepley   /* Cleanup points */
640107218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
640207218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
640307218a29SMatthew G. Knepley }
640407218a29SMatthew G. Knepley 
6405552f7358SJed Brown /*@C
6406552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6407552f7358SJed Brown 
6408552f7358SJed Brown   Not collective
6409552f7358SJed Brown 
6410552f7358SJed Brown   Input Parameters:
6411a1cb98faSBarry Smith + dm      - The `DM`
641220f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6413552f7358SJed Brown . v       - The local vector
6414a1cb98faSBarry Smith - point   - The point in the `DM`
6415552f7358SJed Brown 
64166b867d5aSJose E. Roman   Input/Output Parameters:
641720f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
641820f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
641920f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
642022c1ee49SMatthew G. Knepley 
6421552f7358SJed Brown   Level: intermediate
6422552f7358SJed Brown 
6423a1cb98faSBarry Smith   Notes:
642420f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6425a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6426a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6427a1cb98faSBarry Smith 
6428a1cb98faSBarry Smith   A typical use could be
6429a1cb98faSBarry Smith .vb
6430a1cb98faSBarry Smith    values = NULL;
6431a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6432a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6433a1cb98faSBarry Smith      <Compute on closure>
6434a1cb98faSBarry Smith    }
6435a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6436a1cb98faSBarry Smith .ve
6437a1cb98faSBarry Smith   or
6438a1cb98faSBarry Smith .vb
6439a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6440a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6441a1cb98faSBarry Smith      clSize = clMaxSize;
6442a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6443a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6444a1cb98faSBarry Smith        <Compute on closure>
6445a1cb98faSBarry Smith      }
6446a1cb98faSBarry Smith    }
6447a1cb98faSBarry Smith    PetscFree(values);
6448a1cb98faSBarry Smith .ve
6449a1cb98faSBarry Smith 
645060225df5SJacob Faibussowitsch   Fortran Notes:
645120f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6452a1cb98faSBarry Smith 
64531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6454552f7358SJed Brown @*/
6455d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6456d71ae5a4SJacob Faibussowitsch {
6457d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
6458e8e188d2SZach Atkins   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values));
64593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6460552f7358SJed Brown }
6461552f7358SJed Brown 
6462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6463d71ae5a4SJacob Faibussowitsch {
6464e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6465e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6466e5c487bfSMatthew G. Knepley   IS                 clPoints;
6467e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6468e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6469e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6470c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6471c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6472e5c487bfSMatthew G. Knepley 
6473e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6474e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64759566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6476e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6477e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
64799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
64809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6481e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
64829566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
64833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6484e5c487bfSMatthew G. Knepley   }
6485e5c487bfSMatthew G. Knepley   /* Get points */
648607218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6487c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6488c459fbc1SJed Brown     PetscInt dof;
64899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6490c459fbc1SJed Brown     clsize += dof;
6491c459fbc1SJed Brown   }
64929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6493e5c487bfSMatthew G. Knepley   /* Filter points */
6494e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6495e5c487bfSMatthew G. Knepley     PetscInt dep;
6496e5c487bfSMatthew G. Knepley 
64979566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6498e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6499e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6500e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6501e5c487bfSMatthew G. Knepley     ++Np;
6502e5c487bfSMatthew G. Knepley   }
6503e5c487bfSMatthew G. Knepley   /* Get array */
6504e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6505e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6506e5c487bfSMatthew G. Knepley 
6507e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
65089566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6509e5c487bfSMatthew G. Knepley       asize += dof;
6510e5c487bfSMatthew G. Knepley     }
6511e5c487bfSMatthew G. Knepley     if (!values) {
65129566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6513e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
65143ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6515e5c487bfSMatthew G. Knepley     }
65169566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6517e5c487bfSMatthew G. Knepley   } else {
6518e5c487bfSMatthew G. Knepley     array = *values;
6519e5c487bfSMatthew G. Knepley   }
65209566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6521e5c487bfSMatthew G. Knepley   /* Get values */
65229566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
65239566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6524e5c487bfSMatthew G. Knepley   /* Cleanup points */
65259566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6526e5c487bfSMatthew G. Knepley   /* Cleanup array */
65279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6528e5c487bfSMatthew G. Knepley   if (!*values) {
6529e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6530e5c487bfSMatthew G. Knepley     *values = array;
6531e5c487bfSMatthew G. Knepley   } else {
653263a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6533e5c487bfSMatthew G. Knepley     *csize = size;
6534e5c487bfSMatthew G. Knepley   }
65353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6536e5c487bfSMatthew G. Knepley }
6537e5c487bfSMatthew G. Knepley 
6538552f7358SJed Brown /*@C
6539552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6540552f7358SJed Brown 
6541552f7358SJed Brown   Not collective
6542552f7358SJed Brown 
6543552f7358SJed Brown   Input Parameters:
6544a1cb98faSBarry Smith + dm      - The `DM`
654520f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6546552f7358SJed Brown . v       - The local vector
6547a1cb98faSBarry Smith . point   - The point in the `DM`
654820f4b53cSBarry Smith . csize   - The number of values in the closure, or `NULL`
6549552f7358SJed Brown - values  - The array of values, which is a borrowed array and should not be freed
6550552f7358SJed Brown 
6551552f7358SJed Brown   Level: intermediate
6552552f7358SJed Brown 
6553a1cb98faSBarry Smith   Note:
655420f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6555a1cb98faSBarry Smith 
655660225df5SJacob Faibussowitsch   Fortran Notes:
655720f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6558a1cb98faSBarry Smith 
65591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6560552f7358SJed Brown @*/
6561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6562d71ae5a4SJacob Faibussowitsch {
6563552f7358SJed Brown   PetscInt size = 0;
6564552f7358SJed Brown 
6565552f7358SJed Brown   PetscFunctionBegin;
6566552f7358SJed Brown   /* Should work without recalculating size */
65679566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6568c9fdaa05SMatthew G. Knepley   *values = NULL;
65693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6570552f7358SJed Brown }
6571552f7358SJed Brown 
6572d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6573d71ae5a4SJacob Faibussowitsch {
65749371c9d4SSatish Balay   *x += y;
65759371c9d4SSatish Balay }
6576d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6577d71ae5a4SJacob Faibussowitsch {
65789371c9d4SSatish Balay   *x = y;
65799371c9d4SSatish Balay }
6580552f7358SJed Brown 
6581d71ae5a4SJacob 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[])
6582d71ae5a4SJacob Faibussowitsch {
6583552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6584552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6585552f7358SJed Brown   PetscScalar    *a;
6586552f7358SJed Brown   PetscInt        off, cind = 0, k;
6587552f7358SJed Brown 
6588552f7358SJed Brown   PetscFunctionBegin;
65899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
65909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6591552f7358SJed Brown   a = &array[off];
6592552f7358SJed Brown   if (!cdof || setBC) {
659397e99dd9SToby Isaac     if (clperm) {
65949371c9d4SSatish Balay       if (perm) {
6595ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6596552f7358SJed Brown       } else {
6597ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
65989371c9d4SSatish Balay       }
65999371c9d4SSatish Balay     } else {
66009371c9d4SSatish Balay       if (perm) {
6601ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
66029371c9d4SSatish Balay       } else {
6603ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
66049371c9d4SSatish Balay       }
6605552f7358SJed Brown     }
6606552f7358SJed Brown   } else {
66079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
660897e99dd9SToby Isaac     if (clperm) {
66099371c9d4SSatish Balay       if (perm) {
66109371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
66119371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66129371c9d4SSatish Balay             ++cind;
66139371c9d4SSatish Balay             continue;
66149371c9d4SSatish Balay           }
661597e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6616552f7358SJed Brown         }
6617552f7358SJed Brown       } else {
6618552f7358SJed Brown         for (k = 0; k < dof; ++k) {
66199371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66209371c9d4SSatish Balay             ++cind;
66219371c9d4SSatish Balay             continue;
66229371c9d4SSatish Balay           }
662397e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
662497e99dd9SToby Isaac         }
662597e99dd9SToby Isaac       }
662697e99dd9SToby Isaac     } else {
662797e99dd9SToby Isaac       if (perm) {
662897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66299371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66309371c9d4SSatish Balay             ++cind;
66319371c9d4SSatish Balay             continue;
66329371c9d4SSatish Balay           }
663397e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
663497e99dd9SToby Isaac         }
663597e99dd9SToby Isaac       } else {
663697e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66379371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66389371c9d4SSatish Balay             ++cind;
66399371c9d4SSatish Balay             continue;
66409371c9d4SSatish Balay           }
664197e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
664297e99dd9SToby Isaac         }
6643552f7358SJed Brown       }
6644552f7358SJed Brown     }
6645552f7358SJed Brown   }
66463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6647552f7358SJed Brown }
6648552f7358SJed Brown 
6649d71ae5a4SJacob 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[])
6650d71ae5a4SJacob Faibussowitsch {
6651a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6652a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6653a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6654a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6655a5e93ea8SMatthew G. Knepley 
6656a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
66579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
66589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6659a5e93ea8SMatthew G. Knepley   a = &array[off];
6660a5e93ea8SMatthew G. Knepley   if (cdof) {
66619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
666297e99dd9SToby Isaac     if (clperm) {
666397e99dd9SToby Isaac       if (perm) {
6664a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6665a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
666697e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
666797e99dd9SToby Isaac             cind++;
6668a5e93ea8SMatthew G. Knepley           }
6669a5e93ea8SMatthew G. Knepley         }
6670a5e93ea8SMatthew G. Knepley       } else {
6671a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6672a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
667397e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
667497e99dd9SToby Isaac             cind++;
667597e99dd9SToby Isaac           }
667697e99dd9SToby Isaac         }
667797e99dd9SToby Isaac       }
667897e99dd9SToby Isaac     } else {
667997e99dd9SToby Isaac       if (perm) {
668097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
668197e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
668297e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
668397e99dd9SToby Isaac             cind++;
668497e99dd9SToby Isaac           }
668597e99dd9SToby Isaac         }
668697e99dd9SToby Isaac       } else {
668797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
668897e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
668997e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
669097e99dd9SToby Isaac             cind++;
669197e99dd9SToby Isaac           }
6692a5e93ea8SMatthew G. Knepley         }
6693a5e93ea8SMatthew G. Knepley       }
6694a5e93ea8SMatthew G. Knepley     }
6695a5e93ea8SMatthew G. Knepley   }
66963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6697a5e93ea8SMatthew G. Knepley }
6698a5e93ea8SMatthew G. Knepley 
6699d71ae5a4SJacob 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[])
6700d71ae5a4SJacob Faibussowitsch {
6701552f7358SJed Brown   PetscScalar    *a;
67021a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67031a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
670497e99dd9SToby Isaac   PetscInt        cind = 0, b;
6705552f7358SJed Brown 
6706552f7358SJed Brown   PetscFunctionBegin;
67079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67101a271a75SMatthew G. Knepley   a = &array[foff];
6711552f7358SJed Brown   if (!fcdof || setBC) {
671297e99dd9SToby Isaac     if (clperm) {
67139371c9d4SSatish Balay       if (perm) {
6714ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6715552f7358SJed Brown       } else {
6716ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
67179371c9d4SSatish Balay       }
67189371c9d4SSatish Balay     } else {
67199371c9d4SSatish Balay       if (perm) {
6720ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
67219371c9d4SSatish Balay       } else {
6722ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
67239371c9d4SSatish Balay       }
6724552f7358SJed Brown     }
6725552f7358SJed Brown   } else {
67269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
672797e99dd9SToby Isaac     if (clperm) {
672897e99dd9SToby Isaac       if (perm) {
672997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67309371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67319371c9d4SSatish Balay             ++cind;
67329371c9d4SSatish Balay             continue;
67339371c9d4SSatish Balay           }
673497e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6735552f7358SJed Brown         }
6736552f7358SJed Brown       } else {
673797e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67389371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67399371c9d4SSatish Balay             ++cind;
67409371c9d4SSatish Balay             continue;
67419371c9d4SSatish Balay           }
674297e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
674397e99dd9SToby Isaac         }
674497e99dd9SToby Isaac       }
674597e99dd9SToby Isaac     } else {
674697e99dd9SToby Isaac       if (perm) {
674797e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67489371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67499371c9d4SSatish Balay             ++cind;
67509371c9d4SSatish Balay             continue;
67519371c9d4SSatish Balay           }
675297e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
675397e99dd9SToby Isaac         }
675497e99dd9SToby Isaac       } else {
675597e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67569371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67579371c9d4SSatish Balay             ++cind;
67589371c9d4SSatish Balay             continue;
67599371c9d4SSatish Balay           }
676097e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6761552f7358SJed Brown         }
6762552f7358SJed Brown       }
6763552f7358SJed Brown     }
6764552f7358SJed Brown   }
67651a271a75SMatthew G. Knepley   *offset += fdof;
67663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6767552f7358SJed Brown }
6768552f7358SJed Brown 
6769d71ae5a4SJacob 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[])
6770d71ae5a4SJacob Faibussowitsch {
6771a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
67721a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67731a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67745da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6775ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6776a5e93ea8SMatthew G. Knepley 
6777a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
67789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
67799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67821a271a75SMatthew G. Knepley   a = &array[foff];
6783a5e93ea8SMatthew G. Knepley   if (fcdof) {
6784ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
67859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
678697e99dd9SToby Isaac     if (clperm) {
678797e99dd9SToby Isaac       if (perm) {
6788ba322698SMatthew G. Knepley         if (comps) {
6789ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6790ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
67919371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
67929371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
67939371c9d4SSatish Balay               ncSet = PETSC_TRUE;
67949371c9d4SSatish Balay             }
67959371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
67969371c9d4SSatish Balay               ++cind;
67979371c9d4SSatish Balay               fcSet = PETSC_TRUE;
67989371c9d4SSatish Balay             }
6799ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6800ba322698SMatthew G. Knepley           }
6801ba322698SMatthew G. Knepley         } else {
680297e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
680397e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
680497e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6805a5e93ea8SMatthew G. Knepley               ++cind;
6806a5e93ea8SMatthew G. Knepley             }
6807a5e93ea8SMatthew G. Knepley           }
6808ba322698SMatthew G. Knepley         }
6809ba322698SMatthew G. Knepley       } else {
6810ba322698SMatthew G. Knepley         if (comps) {
6811ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6812ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68139371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68149371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68159371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68169371c9d4SSatish Balay             }
68179371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68189371c9d4SSatish Balay               ++cind;
68199371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68209371c9d4SSatish Balay             }
6821ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6822ba322698SMatthew G. Knepley           }
6823a5e93ea8SMatthew G. Knepley         } else {
682497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
682597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
682697e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
682797e99dd9SToby Isaac               ++cind;
682897e99dd9SToby Isaac             }
682997e99dd9SToby Isaac           }
683097e99dd9SToby Isaac         }
6831ba322698SMatthew G. Knepley       }
683297e99dd9SToby Isaac     } else {
683397e99dd9SToby Isaac       if (perm) {
6834ba322698SMatthew G. Knepley         if (comps) {
6835ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6836ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68379371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68389371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68399371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68409371c9d4SSatish Balay             }
68419371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68429371c9d4SSatish Balay               ++cind;
68439371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68449371c9d4SSatish Balay             }
6845ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6846ba322698SMatthew G. Knepley           }
6847ba322698SMatthew G. Knepley         } else {
684897e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
684997e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
685097e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
685197e99dd9SToby Isaac               ++cind;
685297e99dd9SToby Isaac             }
685397e99dd9SToby Isaac           }
6854ba322698SMatthew G. Knepley         }
6855ba322698SMatthew G. Knepley       } else {
6856ba322698SMatthew G. Knepley         if (comps) {
6857ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6858ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68599371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68609371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68619371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68629371c9d4SSatish Balay             }
68639371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68649371c9d4SSatish Balay               ++cind;
68659371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68669371c9d4SSatish Balay             }
6867ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6868ba322698SMatthew G. Knepley           }
686997e99dd9SToby Isaac         } else {
687097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
687197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
687297e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6873a5e93ea8SMatthew G. Knepley               ++cind;
6874a5e93ea8SMatthew G. Knepley             }
6875a5e93ea8SMatthew G. Knepley           }
6876a5e93ea8SMatthew G. Knepley         }
6877a5e93ea8SMatthew G. Knepley       }
6878a5e93ea8SMatthew G. Knepley     }
6879ba322698SMatthew G. Knepley   }
68801a271a75SMatthew G. Knepley   *offset += fdof;
68813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6882a5e93ea8SMatthew G. Knepley }
6883a5e93ea8SMatthew G. Knepley 
6884d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6885d71ae5a4SJacob Faibussowitsch {
6886552f7358SJed Brown   PetscScalar    *array;
68871b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
68881b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6889552f7358SJed Brown 
68901b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
68919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
68929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
68939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
68949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
68959566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6896b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6897b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6898b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6899b6ebb6e6SMatthew G. Knepley 
69009371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
69019371c9d4SSatish Balay       dof = 0;
69029371c9d4SSatish Balay       continue;
69039371c9d4SSatish Balay     }
69049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6905b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6906b6ebb6e6SMatthew G. Knepley     {
6907b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6908b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6909b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6910b6ebb6e6SMatthew G. Knepley 
69119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
69129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6913b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6914b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6915b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6916ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6917b6ebb6e6SMatthew G. Knepley         } else {
6918ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6919b6ebb6e6SMatthew G. Knepley         }
6920b6ebb6e6SMatthew G. Knepley       } else {
69219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6922b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6923b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69249371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69259371c9d4SSatish Balay               ++cind;
69269371c9d4SSatish Balay               continue;
69279371c9d4SSatish Balay             }
6928b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6929b6ebb6e6SMatthew G. Knepley           }
6930b6ebb6e6SMatthew G. Knepley         } else {
6931b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69329371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69339371c9d4SSatish Balay               ++cind;
69349371c9d4SSatish Balay               continue;
69359371c9d4SSatish Balay             }
6936b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6937b6ebb6e6SMatthew G. Knepley           }
6938b6ebb6e6SMatthew G. Knepley         }
6939b6ebb6e6SMatthew G. Knepley       }
6940b6ebb6e6SMatthew G. Knepley     }
6941b6ebb6e6SMatthew G. Knepley   }
69429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6944b6ebb6e6SMatthew G. Knepley }
69451b406b76SMatthew G. Knepley 
69461b406b76SMatthew G. Knepley /*@C
694720f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
69481b406b76SMatthew G. Knepley 
69491b406b76SMatthew G. Knepley   Not collective
69501b406b76SMatthew G. Knepley 
69511b406b76SMatthew G. Knepley   Input Parameters:
6952a1cb98faSBarry Smith + dm      - The `DM`
695320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
69541b406b76SMatthew G. Knepley . v       - The local vector
695520f4b53cSBarry Smith . point   - The point in the `DM`
69561b406b76SMatthew G. Knepley . values  - The array of values
6957a1cb98faSBarry Smith - mode    - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6958a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
69591b406b76SMatthew G. Knepley 
69601b406b76SMatthew G. Knepley   Level: intermediate
69611b406b76SMatthew G. Knepley 
69621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
69631b406b76SMatthew G. Knepley @*/
6964d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6965d71ae5a4SJacob Faibussowitsch {
69661b406b76SMatthew G. Knepley   PetscSection    clSection;
69671b406b76SMatthew G. Knepley   IS              clPoints;
69681b406b76SMatthew G. Knepley   PetscScalar    *array;
69691b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
697027f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6971c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
69721b406b76SMatthew G. Knepley 
69731a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
69741b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69759566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
69761a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
69771a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
69789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
69799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
69801b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
69819566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
69823ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
69831b406b76SMatthew G. Knepley   }
69841a271a75SMatthew G. Knepley   /* Get points */
698507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6986c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6987c459fbc1SJed Brown     PetscInt dof;
69889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6989c459fbc1SJed Brown     clsize += dof;
6990c459fbc1SJed Brown   }
69919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
69921a271a75SMatthew G. Knepley   /* Get array */
69939566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
69941a271a75SMatthew G. Knepley   /* Get values */
6995ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
699697e99dd9SToby Isaac     PetscInt offset = 0, f;
6997552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
699897e99dd9SToby Isaac       const PetscInt    **perms = NULL;
699997e99dd9SToby Isaac       const PetscScalar **flips = NULL;
700097e99dd9SToby Isaac 
70019566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7002552f7358SJed Brown       switch (mode) {
7003552f7358SJed Brown       case INSERT_VALUES:
700497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
700597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
700697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
700797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70083ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
70099371c9d4SSatish Balay         }
70109371c9d4SSatish Balay         break;
7011552f7358SJed Brown       case INSERT_ALL_VALUES:
701297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
701397e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
701497e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
701597e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70163ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
70179371c9d4SSatish Balay         }
70189371c9d4SSatish Balay         break;
7019a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
702097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
702197e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
702297e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
702397e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70243ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
70259371c9d4SSatish Balay         }
70269371c9d4SSatish Balay         break;
7027552f7358SJed Brown       case ADD_VALUES:
702897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
702997e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
703097e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
703197e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70323ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
70339371c9d4SSatish Balay         }
70349371c9d4SSatish Balay         break;
7035552f7358SJed Brown       case ADD_ALL_VALUES:
703697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
703797e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
703897e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
703997e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70403ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
70419371c9d4SSatish Balay         }
70429371c9d4SSatish Balay         break;
7043304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
704497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
704597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
704697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
704797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70483ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
70499371c9d4SSatish Balay         }
70509371c9d4SSatish Balay         break;
7051d71ae5a4SJacob Faibussowitsch       default:
7052d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7053552f7358SJed Brown       }
70549566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
70551a271a75SMatthew G. Knepley     }
7056552f7358SJed Brown   } else {
70571a271a75SMatthew G. Knepley     PetscInt            dof, off;
705897e99dd9SToby Isaac     const PetscInt    **perms = NULL;
705997e99dd9SToby Isaac     const PetscScalar **flips = NULL;
70601a271a75SMatthew G. Knepley 
70619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
7062552f7358SJed Brown     switch (mode) {
7063552f7358SJed Brown     case INSERT_VALUES:
706497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
706597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
706697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
706797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70689566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70693ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
70709371c9d4SSatish Balay       }
70719371c9d4SSatish Balay       break;
7072552f7358SJed Brown     case INSERT_ALL_VALUES:
707397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
707497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
707597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
707697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70779566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70783ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
70799371c9d4SSatish Balay       }
70809371c9d4SSatish Balay       break;
7081a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
708297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
708397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
708497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
708597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70869566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70873ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
70889371c9d4SSatish Balay       }
70899371c9d4SSatish Balay       break;
7090552f7358SJed Brown     case ADD_VALUES:
709197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
709297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
709397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
709497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70963ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
70979371c9d4SSatish Balay       }
70989371c9d4SSatish Balay       break;
7099552f7358SJed Brown     case ADD_ALL_VALUES:
710097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
710197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
710297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
710397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71053ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
71069371c9d4SSatish Balay       }
71079371c9d4SSatish Balay       break;
7108304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
710997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
711097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
711197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
711297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71139566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71143ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
71159371c9d4SSatish Balay       }
71169371c9d4SSatish Balay       break;
7117d71ae5a4SJacob Faibussowitsch     default:
7118d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7119552f7358SJed Brown     }
71209566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
7121552f7358SJed Brown   }
71221a271a75SMatthew G. Knepley   /* Cleanup points */
71239566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
71241a271a75SMatthew G. Knepley   /* Cleanup array */
71259566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
71263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7127552f7358SJed Brown }
7128552f7358SJed Brown 
71295f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
7130d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
7131d71ae5a4SJacob Faibussowitsch {
71325f790a90SMatthew G. Knepley   PetscFunctionBegin;
713311cc89d2SBarry Smith   *contains = PETSC_TRUE;
71345f790a90SMatthew G. Knepley   if (label) {
7135d6177c40SToby Isaac     PetscInt fdof;
71365f790a90SMatthew G. Knepley 
713711cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
713811cc89d2SBarry Smith     if (!*contains) {
71399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
71405f790a90SMatthew G. Knepley       *offset += fdof;
71413ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
71425f790a90SMatthew G. Knepley     }
71435f790a90SMatthew G. Knepley   }
71443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71455f790a90SMatthew G. Knepley }
71465f790a90SMatthew G. Knepley 
714797529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
7148d71ae5a4SJacob 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)
7149d71ae5a4SJacob Faibussowitsch {
7150e07394fbSMatthew G. Knepley   PetscSection    clSection;
7151e07394fbSMatthew G. Knepley   IS              clPoints;
7152e07394fbSMatthew G. Knepley   PetscScalar    *array;
7153e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
715497529cf3SJed Brown   const PetscInt *clp;
7155e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
715697e99dd9SToby Isaac   PetscInt        offset = 0, f;
7157e07394fbSMatthew G. Knepley 
7158e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
7159e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
7161e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7162e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
71639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7164e07394fbSMatthew G. Knepley   /* Get points */
716507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
7166e07394fbSMatthew G. Knepley   /* Get array */
71679566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
7168e07394fbSMatthew G. Knepley   /* Get values */
7169e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
717097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
717197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
717211cc89d2SBarry Smith     PetscBool           contains;
717397e99dd9SToby Isaac 
7174e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
7175e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
7176e07394fbSMatthew G. Knepley         PetscInt fdof;
71779566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
7178e07394fbSMatthew G. Knepley         offset += fdof;
7179e07394fbSMatthew G. Knepley       }
7180e07394fbSMatthew G. Knepley       continue;
7181e07394fbSMatthew G. Knepley     }
71829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7183e07394fbSMatthew G. Knepley     switch (mode) {
7184e07394fbSMatthew G. Knepley     case INSERT_VALUES:
718597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
718697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
718797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
718897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
718911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
719011cc89d2SBarry Smith         if (!contains) continue;
71919566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
71929371c9d4SSatish Balay       }
71939371c9d4SSatish Balay       break;
7194e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
719597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
719697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
719797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
719897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
719911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
720011cc89d2SBarry Smith         if (!contains) continue;
72019566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
72029371c9d4SSatish Balay       }
72039371c9d4SSatish Balay       break;
7204e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
720597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
720697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
720797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
720897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
720911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
721011cc89d2SBarry Smith         if (!contains) continue;
72119566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
72129371c9d4SSatish Balay       }
72139371c9d4SSatish Balay       break;
7214e07394fbSMatthew G. Knepley     case ADD_VALUES:
721597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
721697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
721797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
721897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
721911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
722011cc89d2SBarry Smith         if (!contains) continue;
72219566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
72229371c9d4SSatish Balay       }
72239371c9d4SSatish Balay       break;
7224e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
722597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
722697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
722797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
722897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
722911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
723011cc89d2SBarry Smith         if (!contains) continue;
72319566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
72329371c9d4SSatish Balay       }
72339371c9d4SSatish Balay       break;
7234d71ae5a4SJacob Faibussowitsch     default:
7235d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7236e07394fbSMatthew G. Knepley     }
72379566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7238e07394fbSMatthew G. Knepley   }
7239e07394fbSMatthew G. Knepley   /* Cleanup points */
72409566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
7241e07394fbSMatthew G. Knepley   /* Cleanup array */
72429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
72433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7244e07394fbSMatthew G. Knepley }
7245e07394fbSMatthew G. Knepley 
7246d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
7247d71ae5a4SJacob Faibussowitsch {
7248552f7358SJed Brown   PetscMPIInt rank;
7249552f7358SJed Brown   PetscInt    i, j;
7250552f7358SJed Brown 
7251552f7358SJed Brown   PetscFunctionBegin;
72529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
725363a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
725463a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
725563a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
7256b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
72573ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
7258b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
72599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
7260b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
7261519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
72629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
7263552f7358SJed Brown #else
72649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
7265552f7358SJed Brown #endif
7266552f7358SJed Brown     }
72679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
7268552f7358SJed Brown   }
72693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7270552f7358SJed Brown }
7271552f7358SJed Brown 
727205586334SMatthew G. Knepley /*
727305586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
727405586334SMatthew G. Knepley 
727505586334SMatthew G. Knepley   Input Parameters:
727605586334SMatthew G. Knepley + section - The section for this data layout
727736fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
727805586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
727905586334SMatthew G. Knepley . off     - The global offset of this point
728005586334SMatthew G. Knepley . loff    - The local offset of each field
7281a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
728205586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
728305586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
728405586334SMatthew G. Knepley 
728505586334SMatthew G. Knepley   Output Parameter:
728605586334SMatthew G. Knepley . indices - Indices for dofs on this point
728705586334SMatthew G. Knepley 
728805586334SMatthew G. Knepley   Level: developer
728905586334SMatthew G. Knepley 
729005586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
729105586334SMatthew G. Knepley */
7292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
7293d71ae5a4SJacob Faibussowitsch {
7294e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
7295552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7296552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7297552f7358SJed Brown   PetscInt        cind = 0, k;
7298552f7358SJed Brown 
7299552f7358SJed Brown   PetscFunctionBegin;
730008401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
73029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
7303552f7358SJed Brown   if (!cdof || setBC) {
730405586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
730505586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
730605586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
730705586334SMatthew G. Knepley 
730805586334SMatthew G. Knepley       indices[ind] = off + k;
7309552f7358SJed Brown     }
7310552f7358SJed Brown   } else {
73119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
73124acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
731305586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
731405586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
731505586334SMatthew G. Knepley 
73164acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
73174acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
731805586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
73194acb8e1eSToby Isaac         ++cind;
73204acb8e1eSToby Isaac       } else {
732136fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7322552f7358SJed Brown       }
7323552f7358SJed Brown     }
7324552f7358SJed Brown   }
7325e6ccafaeSMatthew G Knepley   *loff += dof;
73263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7327552f7358SJed Brown }
7328552f7358SJed Brown 
73297e29afd2SMatthew G. Knepley /*
733036fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
73317e29afd2SMatthew G. Knepley 
733236fa2b79SJed Brown  Input Parameters:
733336fa2b79SJed Brown + section - a section (global or local)
733420f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
733536fa2b79SJed Brown . point - point within section
733636fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
733736fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
733836fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
733936fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
734036fa2b79SJed Brown . permsoff - offset
734136fa2b79SJed Brown - indperm - index permutation
734236fa2b79SJed Brown 
734336fa2b79SJed Brown  Output Parameter:
734436fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
734536fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
734636fa2b79SJed Brown 
734736fa2b79SJed Brown  Notes:
734836fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
734936fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
735036fa2b79SJed Brown  in the local vector.
735136fa2b79SJed Brown 
735236fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
735336fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
735436fa2b79SJed Brown 
735536fa2b79SJed Brown  Developer Note:
735636fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
735736fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
735836fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
735936fa2b79SJed Brown 
736036fa2b79SJed Brown  Example:
736136fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
736236fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
736336fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
736436fa2b79SJed 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.
736536fa2b79SJed Brown 
736636fa2b79SJed Brown  Level: developer
73677e29afd2SMatthew G. Knepley */
7368d71ae5a4SJacob 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[])
7369d71ae5a4SJacob Faibussowitsch {
7370552f7358SJed Brown   PetscInt numFields, foff, f;
7371552f7358SJed Brown 
7372552f7358SJed Brown   PetscFunctionBegin;
737308401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7375552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
73764acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7377552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
73784acb8e1eSToby Isaac     PetscInt        cind = 0, b;
73794acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7380552f7358SJed Brown 
73819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
73829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7383552f7358SJed Brown     if (!cfdof || setBC) {
738405586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
738505586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
738605586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
738705586334SMatthew G. Knepley 
738805586334SMatthew G. Knepley         indices[ind] = off + foff + b;
738905586334SMatthew G. Knepley       }
7390552f7358SJed Brown     } else {
73919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
739205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
739305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
739405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
739505586334SMatthew G. Knepley 
73964acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
739705586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7398552f7358SJed Brown           ++cind;
7399552f7358SJed Brown         } else {
740036fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7401552f7358SJed Brown         }
7402552f7358SJed Brown       }
7403552f7358SJed Brown     }
740436fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7405552f7358SJed Brown     foffs[f] += fdof;
7406552f7358SJed Brown   }
74073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7408552f7358SJed Brown }
7409552f7358SJed Brown 
74107e29afd2SMatthew G. Knepley /*
74117e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
74127e29afd2SMatthew G. Knepley 
74137e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7414645102dcSJed Brown 
7415645102dcSJed Brown  Notes:
7416645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7417645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
74187e29afd2SMatthew G. Knepley */
7419d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7420d71ae5a4SJacob Faibussowitsch {
74217e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
74227e29afd2SMatthew G. Knepley 
74237e29afd2SMatthew G. Knepley   PetscFunctionBegin;
74249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
74257e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
74267e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
74277e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
74287e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
74297e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
74307e29afd2SMatthew G. Knepley 
74319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
74329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
74339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7434645102dcSJed Brown     if (!cfdof) {
743505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
743605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
743705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
743805586334SMatthew G. Knepley 
743905586334SMatthew G. Knepley         indices[ind] = foff + b;
744005586334SMatthew G. Knepley       }
74417e29afd2SMatthew G. Knepley     } else {
74429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
744305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
744405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
744505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
744605586334SMatthew G. Knepley 
74477e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
744805586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
74497e29afd2SMatthew G. Knepley           ++cind;
74507e29afd2SMatthew G. Knepley         } else {
745105586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
74527e29afd2SMatthew G. Knepley         }
74537e29afd2SMatthew G. Knepley       }
74547e29afd2SMatthew G. Knepley     }
74557e29afd2SMatthew G. Knepley     foffs[f] += fdof;
74567e29afd2SMatthew G. Knepley   }
74573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74587e29afd2SMatthew G. Knepley }
74597e29afd2SMatthew G. Knepley 
7460c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms)
7461c789d87fSToby Isaac {
7462c789d87fSToby Isaac   PetscInt numFields, sStart, sEnd, cStart, cEnd;
7463c789d87fSToby Isaac 
7464c789d87fSToby Isaac   PetscFunctionBegin;
7465c789d87fSToby Isaac   PetscCall(PetscSectionGetNumFields(section, &numFields));
7466c789d87fSToby Isaac   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
7467c789d87fSToby Isaac   PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd));
7468c789d87fSToby Isaac   for (PetscInt p = 0; p < nPoints; p++) {
7469c789d87fSToby Isaac     PetscInt     b       = pnts[2 * p];
7470c789d87fSToby Isaac     PetscInt     bSecDof = 0, bOff;
7471c789d87fSToby Isaac     PetscInt     cSecDof = 0;
7472c789d87fSToby Isaac     PetscSection indices_section;
7473c789d87fSToby Isaac 
7474c789d87fSToby Isaac     if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7475c789d87fSToby Isaac     if (!bSecDof) continue;
7476c789d87fSToby Isaac     if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof));
7477c789d87fSToby Isaac     indices_section = cSecDof > 0 ? cSec : section;
7478c789d87fSToby Isaac     if (numFields) {
7479c789d87fSToby Isaac       PetscInt fStart[32], fEnd[32];
7480c789d87fSToby Isaac 
7481c789d87fSToby Isaac       fStart[0] = 0;
7482c789d87fSToby Isaac       fEnd[0]   = 0;
7483c789d87fSToby Isaac       for (PetscInt f = 0; f < numFields; f++) {
7484c789d87fSToby Isaac         PetscInt fDof = 0;
7485c789d87fSToby Isaac 
7486c789d87fSToby Isaac         PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof));
7487c789d87fSToby Isaac         fStart[f + 1] = fStart[f] + fDof;
7488c789d87fSToby Isaac         fEnd[f + 1]   = fStart[f + 1];
7489c789d87fSToby Isaac       }
7490c789d87fSToby Isaac       PetscCall(PetscSectionGetOffset(indices_section, b, &bOff));
7491c789d87fSToby Isaac       // only apply permutations on one side
7492c789d87fSToby Isaac       PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices));
7493c789d87fSToby Isaac       for (PetscInt f = 0; f < numFields; f++) {
7494c789d87fSToby Isaac         for (PetscInt i = fStart[f]; i < fEnd[f]; i++) { indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); }
7495c789d87fSToby Isaac       }
7496c789d87fSToby Isaac     } else {
7497c789d87fSToby Isaac       PetscInt bEnd = 0;
7498c789d87fSToby Isaac 
7499c789d87fSToby Isaac       PetscCall(PetscSectionGetOffset(indices_section, b, &bOff));
7500c789d87fSToby Isaac       PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices));
7501c789d87fSToby Isaac 
7502c789d87fSToby Isaac       for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1);
7503c789d87fSToby Isaac     }
7504c789d87fSToby Isaac   }
7505c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7506c789d87fSToby Isaac }
7507c789d87fSToby Isaac 
7508c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsGetSubMatModification(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscInt offsets[], PetscScalar *outMat[])
7509d71ae5a4SJacob Faibussowitsch {
7510d3d1a6afSToby Isaac   Mat             cMat;
7511d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7512d3d1a6afSToby Isaac   IS              aIS;
7513d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7514a19ea1e9SMatthew G. Knepley   PetscInt        sStart = -1, sEnd = -1;
7515a19ea1e9SMatthew G. Knepley   PetscInt        cStart = -1, cEnd = -1;
7516d3d1a6afSToby Isaac   const PetscInt *anchors;
7517e969e7a5SJose E. Roman   PetscInt        numFields, p;
7518d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7519c789d87fSToby Isaac   PetscInt       *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices;
7520c789d87fSToby Isaac   PetscInt        oldOffsets[32];
7521d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7522c789d87fSToby Isaac   PetscInt        oldOffsetsCopy[32];
7523c789d87fSToby Isaac   PetscInt        newOffsetsCopy[32];
7524c789d87fSToby Isaac   PetscScalar    *modMat         = NULL;
7525d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7526d3d1a6afSToby Isaac 
7527d3d1a6afSToby Isaac   PetscFunctionBegin;
7528d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7529d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7531d3d1a6afSToby Isaac 
75329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7533d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7534d3d1a6afSToby Isaac   if (aSec) {
75359566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
7536c789d87fSToby Isaac     PetscCall(PetscArrayzero(oldOffsets, 32));
75379566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
75389566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7539a19ea1e9SMatthew G. Knepley     PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
7540d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7541d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7542d3d1a6afSToby Isaac      * into the global matrix anyway) */
7543d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7544d3d1a6afSToby Isaac       PetscInt b    = points[p];
7545a19ea1e9SMatthew G. Knepley       PetscInt bDof = 0, bSecDof = 0;
7546d3d1a6afSToby Isaac 
7547a19ea1e9SMatthew G. Knepley       if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7548ad540459SPierre Jolivet       if (!bSecDof) continue;
7549c789d87fSToby Isaac 
7550c789d87fSToby Isaac       for (PetscInt f = 0; f < numFields; f++) {
7551c789d87fSToby Isaac         PetscInt fDof = 0;
7552c789d87fSToby Isaac 
7553c789d87fSToby Isaac         PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7554c789d87fSToby Isaac         oldOffsets[f + 1] += fDof;
7555c789d87fSToby Isaac       }
755648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7557d3d1a6afSToby Isaac       if (bDof) {
7558d3d1a6afSToby Isaac         /* this point is constrained */
7559d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7560d3d1a6afSToby Isaac         PetscInt bOff, q;
7561d3d1a6afSToby Isaac 
75629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7563d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7564d3d1a6afSToby Isaac           PetscInt a    = anchors[bOff + q];
7565a19ea1e9SMatthew G. Knepley           PetscInt aDof = 0;
7566d3d1a6afSToby Isaac 
7567a19ea1e9SMatthew G. Knepley           if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof));
7568c789d87fSToby Isaac           if (aDof) {
7569c789d87fSToby Isaac             anyConstrained = PETSC_TRUE;
7570c789d87fSToby Isaac             newNumPoints += 1;
7571c789d87fSToby Isaac           }
7572d3d1a6afSToby Isaac           newNumIndices += aDof;
7573e969e7a5SJose E. Roman           for (PetscInt f = 0; f < numFields; ++f) {
7574a19ea1e9SMatthew G. Knepley             PetscInt fDof = 0;
7575d3d1a6afSToby Isaac 
7576a19ea1e9SMatthew G. Knepley             if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7577d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7578d3d1a6afSToby Isaac           }
7579d3d1a6afSToby Isaac         }
75809371c9d4SSatish Balay       } else {
7581d3d1a6afSToby Isaac         /* this point is not constrained */
7582d3d1a6afSToby Isaac         newNumPoints++;
75834b2f2278SToby Isaac         newNumIndices += bSecDof;
7584e969e7a5SJose E. Roman         for (PetscInt f = 0; f < numFields; ++f) {
7585d3d1a6afSToby Isaac           PetscInt fDof;
7586d3d1a6afSToby Isaac 
75879566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7588d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7589d3d1a6afSToby Isaac         }
7590d3d1a6afSToby Isaac       }
7591d3d1a6afSToby Isaac     }
7592d3d1a6afSToby Isaac   }
7593d3d1a6afSToby Isaac   if (!anyConstrained) {
759472b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
759572b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
759672b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
7597c789d87fSToby Isaac     if (outMat) *outMat = NULL;
75989566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
75993ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7600d3d1a6afSToby Isaac   }
7601d3d1a6afSToby Isaac 
76026ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
76036ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
76046ecaa68aSToby Isaac 
7605e969e7a5SJose E. Roman   for (PetscInt f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7606e969e7a5SJose E. Roman   for (PetscInt f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f];
7607d3d1a6afSToby Isaac 
7608c789d87fSToby Isaac   if (!outPoints && !outMat) {
76096ecaa68aSToby Isaac     if (offsets) {
7610e969e7a5SJose E. Roman       for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
76116ecaa68aSToby Isaac     }
76129566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
76133ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
76146ecaa68aSToby Isaac   }
76156ecaa68aSToby Isaac 
76161dca8a05SBarry 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);
7617c789d87fSToby Isaac   PetscCheck(!numFields || oldOffsets[numFields] == numIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, oldOffsets[numFields], numIndices);
7618d3d1a6afSToby Isaac 
76199566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7620a19ea1e9SMatthew G. Knepley   PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd));
7621d3d1a6afSToby Isaac 
76226ecaa68aSToby Isaac   /* output arrays */
76239566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
7624c789d87fSToby Isaac   PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints));
76256ecaa68aSToby Isaac 
7626c789d87fSToby Isaac   // get the new Points
7627c789d87fSToby Isaac   for (PetscInt p = 0, newP = 0; p < numPoints; p++) {
7628d3d1a6afSToby Isaac     PetscInt b    = points[2 * p];
7629c789d87fSToby Isaac     PetscInt bDof = 0, bSecDof = 0, bOff;
7630d3d1a6afSToby Isaac 
7631a19ea1e9SMatthew G. Knepley     if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7632ad540459SPierre Jolivet     if (!bSecDof) continue;
763348a46eb9SPierre Jolivet     if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7634d3d1a6afSToby Isaac     if (bDof) {
76359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7636c789d87fSToby Isaac       for (PetscInt q = 0; q < bDof; q++) {
7637a19ea1e9SMatthew G. Knepley         PetscInt a = anchors[bOff + q], aDof = 0;
7638d3d1a6afSToby Isaac 
7639a19ea1e9SMatthew G. Knepley         if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof));
7640c789d87fSToby Isaac         if (aDof) {
7641c789d87fSToby Isaac           newPoints[2 * newP]     = a;
7642c789d87fSToby Isaac           newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation
7643d3d1a6afSToby Isaac           newP++;
7644d3d1a6afSToby Isaac         }
7645d3d1a6afSToby Isaac       }
7646d3d1a6afSToby Isaac     } else {
7647d3d1a6afSToby Isaac       newPoints[2 * newP]     = b;
7648c789d87fSToby Isaac       newPoints[2 * newP + 1] = points[2 * p + 1];
7649d3d1a6afSToby Isaac       newP++;
7650d3d1a6afSToby Isaac     }
7651d3d1a6afSToby Isaac   }
7652d3d1a6afSToby Isaac 
7653c789d87fSToby Isaac   if (outMat) {
7654c789d87fSToby Isaac     PetscScalar *tmpMat;
7655c789d87fSToby Isaac     PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32));
7656c789d87fSToby Isaac     PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32));
7657c789d87fSToby Isaac 
7658c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices));
7659c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices));
7660c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices));
7661c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices));
7662c789d87fSToby Isaac 
7663c789d87fSToby Isaac     for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1;
7664c789d87fSToby Isaac     for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1;
7665c789d87fSToby Isaac 
7666c789d87fSToby Isaac     PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms));
7667c789d87fSToby Isaac     PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL));
7668c789d87fSToby Isaac 
7669c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat));
7670c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat));
7671c789d87fSToby Isaac     PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices));
7672c789d87fSToby Isaac     // for each field, insert the anchor modification into modMat
7673c789d87fSToby Isaac     for (PetscInt f = 0; f < PetscMax(1, numFields); f++) {
7674c789d87fSToby Isaac       PetscInt fStart    = oldOffsets[f];
7675c789d87fSToby Isaac       PetscInt fNewStart = newOffsets[f];
7676c789d87fSToby Isaac       for (PetscInt p = 0, newP = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) {
7677c789d87fSToby Isaac         PetscInt b    = points[2 * p];
7678c789d87fSToby Isaac         PetscInt bDof = 0, bSecDof = 0, bOff;
7679c789d87fSToby Isaac 
7680c789d87fSToby Isaac         if (b >= sStart && b < sEnd) {
7681d3d1a6afSToby Isaac           if (numFields) {
7682c789d87fSToby Isaac             PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof));
76839371c9d4SSatish Balay           } else {
7684c789d87fSToby Isaac             PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7685d3d1a6afSToby Isaac           }
7686d3d1a6afSToby Isaac         }
7687c789d87fSToby Isaac         if (!bSecDof) continue;
7688c789d87fSToby Isaac         if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7689c789d87fSToby Isaac         if (bDof) {
7690c789d87fSToby Isaac           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7691c789d87fSToby Isaac           for (PetscInt q = 0; q < bDof; q++, newP++) {
7692c789d87fSToby Isaac             PetscInt a = anchors[bOff + q], aDof = 0;
7693d3d1a6afSToby Isaac 
7694c789d87fSToby Isaac             if (a >= sStart && a < sEnd) {
7695d3d1a6afSToby Isaac               if (numFields) {
7696c789d87fSToby Isaac                 PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
7697c789d87fSToby Isaac               } else {
7698c789d87fSToby Isaac                 PetscCall(PetscSectionGetDof(section, a, &aDof));
7699d3d1a6afSToby Isaac               }
7700d3d1a6afSToby Isaac             }
7701c789d87fSToby Isaac             if (aDof) {
7702c789d87fSToby Isaac               PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat));
7703c789d87fSToby Isaac               for (PetscInt d = 0; d < bSecDof; d++) {
7704c789d87fSToby Isaac                 for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e];
7705c789d87fSToby Isaac               }
7706c789d87fSToby Isaac             }
7707c789d87fSToby Isaac             oNew += aDof;
7708c789d87fSToby Isaac           }
77099371c9d4SSatish Balay         } else {
7710c789d87fSToby Isaac           // Insert the identity matrix in this block
7711c789d87fSToby Isaac           for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1;
7712c789d87fSToby Isaac           oNew += bSecDof;
7713c789d87fSToby Isaac           newP++;
7714d3d1a6afSToby Isaac         }
7715c789d87fSToby Isaac         o += bSecDof;
7716d3d1a6afSToby Isaac       }
7717d3d1a6afSToby Isaac     }
7718d3d1a6afSToby Isaac 
7719c789d87fSToby Isaac     *outMat = modMat;
77206ecaa68aSToby Isaac 
7721c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat));
7722c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices));
7723c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices));
7724c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices));
7725c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices));
7726d3d1a6afSToby Isaac   }
77279566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7728d3d1a6afSToby Isaac 
7729d3d1a6afSToby Isaac   /* output */
77306ecaa68aSToby Isaac   if (outPoints) {
7731d3d1a6afSToby Isaac     *outPoints = newPoints;
77329371c9d4SSatish Balay   } else {
77339566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
77346ecaa68aSToby Isaac   }
7735e969e7a5SJose E. Roman   for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
77363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7737d3d1a6afSToby Isaac }
7738d3d1a6afSToby Isaac 
7739c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsModifyMat_Internal(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt numRows, PetscInt numCols, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyRight, PetscBool multiplyLeft)
7740c789d87fSToby Isaac {
7741c789d87fSToby Isaac   PetscScalar *modMat        = NULL;
7742c789d87fSToby Isaac   PetscInt     newNumIndices = -1;
77437cd05799SMatthew G. Knepley 
7744c789d87fSToby Isaac   PetscFunctionBegin;
7745c789d87fSToby Isaac   /* If M is the matrix represented by values, get the matrix C such that we will add M * C (or, if multiplyLeft, C^T * M * C) into the global matrix.
7746c789d87fSToby Isaac      modMat is that matrix C */
7747c789d87fSToby Isaac   PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL));
7748c789d87fSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
7749c789d87fSToby Isaac   if (modMat) {
7750c789d87fSToby Isaac     const PetscScalar *newValues = values;
77517cd05799SMatthew G. Knepley 
7752c789d87fSToby Isaac     if (multiplyRight) {
7753c789d87fSToby Isaac       PetscScalar *newNewValues = NULL;
7754c789d87fSToby Isaac       PetscBLASInt M            = newNumIndices;
7755c789d87fSToby Isaac       PetscBLASInt N            = numRows;
7756c789d87fSToby Isaac       PetscBLASInt K            = numIndices;
7757c789d87fSToby Isaac       PetscScalar  a = 1.0, b = 0.0;
77587cd05799SMatthew G. Knepley 
7759c789d87fSToby Isaac       PetscCheck(numCols == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of columns: %" PetscInt_FMT ", expected %" PetscInt_FMT, numCols, numIndices);
77607cd05799SMatthew G. Knepley 
7761c789d87fSToby Isaac       PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues));
7762c789d87fSToby Isaac       // row-major to column-major conversion, right multiplication becomes left multiplication
7763c789d87fSToby Isaac       PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M));
776436fa2b79SJed Brown 
7765c789d87fSToby Isaac       numCols   = newNumIndices;
7766c789d87fSToby Isaac       newValues = newNewValues;
7767c789d87fSToby Isaac     }
7768a1cb98faSBarry Smith 
7769c789d87fSToby Isaac     if (multiplyLeft) {
7770c789d87fSToby Isaac       PetscScalar *newNewValues = NULL;
7771c789d87fSToby Isaac       PetscBLASInt M            = numCols;
7772c789d87fSToby Isaac       PetscBLASInt N            = newNumIndices;
7773c789d87fSToby Isaac       PetscBLASInt K            = numIndices;
7774c789d87fSToby Isaac       PetscScalar  a = 1.0, b = 0.0;
77757cd05799SMatthew G. Knepley 
7776c789d87fSToby Isaac       PetscCheck(numRows == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of rows: %" PetscInt_FMT ", expected %" PetscInt_FMT, numRows, numIndices);
7777c789d87fSToby Isaac 
7778c789d87fSToby Isaac       PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues));
7779c789d87fSToby Isaac       // row-major to column-major conversion, left multiplication becomes right multiplication
7780c789d87fSToby Isaac       PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M));
7781c789d87fSToby Isaac       if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues));
7782c789d87fSToby Isaac       newValues = newNewValues;
7783c789d87fSToby Isaac     }
7784c789d87fSToby Isaac     *outValues = (PetscScalar *)newValues;
7785c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat));
7786c789d87fSToby Isaac   }
7787c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7788c789d87fSToby Isaac }
7789c789d87fSToby Isaac 
7790c789d87fSToby Isaac PETSC_INTERN 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)
7791c789d87fSToby Isaac {
7792c789d87fSToby Isaac   PetscFunctionBegin;
7793c789d87fSToby Isaac   PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft));
7794c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7795c789d87fSToby Isaac }
7796c789d87fSToby Isaac 
7797c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize)
7798c789d87fSToby Isaac {
7799c789d87fSToby Isaac   /* Closure ordering */
7800c789d87fSToby Isaac   PetscSection    clSection;
7801c789d87fSToby Isaac   IS              clPoints;
7802c789d87fSToby Isaac   const PetscInt *clp;
7803c789d87fSToby Isaac   PetscInt       *points;
7804c789d87fSToby Isaac   PetscInt        Ncl, Ni = 0;
7805c789d87fSToby Isaac 
7806c789d87fSToby Isaac   PetscFunctionBeginHot;
7807c789d87fSToby Isaac   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7808c789d87fSToby Isaac   for (PetscInt p = 0; p < Ncl * 2; p += 2) {
7809c789d87fSToby Isaac     PetscInt dof;
7810c789d87fSToby Isaac 
7811c789d87fSToby Isaac     PetscCall(PetscSectionGetDof(section, points[p], &dof));
7812c789d87fSToby Isaac     Ni += dof;
7813c789d87fSToby Isaac   }
7814c789d87fSToby Isaac   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7815c789d87fSToby Isaac   *closureSize = Ni;
7816c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7817c789d87fSToby Isaac }
7818c789d87fSToby Isaac 
7819c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndices_Internal(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numRows, PetscInt *numCols, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[], PetscBool multiplyRight, PetscBool multiplyLeft)
7820d71ae5a4SJacob Faibussowitsch {
782171f0bbf9SMatthew G. Knepley   /* Closure ordering */
78227773e69fSMatthew G. Knepley   PetscSection    clSection;
78237773e69fSMatthew G. Knepley   IS              clPoints;
782471f0bbf9SMatthew G. Knepley   const PetscInt *clp;
782571f0bbf9SMatthew G. Knepley   PetscInt       *points;
782671f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
782771f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
78284acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
782971f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
783071f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
783171f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
783271f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
783371f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
783471f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
783571f0bbf9SMatthew G. Knepley 
783671f0bbf9SMatthew G. Knepley   PetscInt *idx;
783771f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
783871f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
78397caea556SToby Isaac   PetscInt  idxStart, idxEnd;
7840c789d87fSToby Isaac   PetscInt  nRows, nCols;
78417773e69fSMatthew G. Knepley 
784271f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
78437773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78447773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
784536fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7846c789d87fSToby Isaac   PetscAssertPointer(numRows, 6);
7847c789d87fSToby Isaac   PetscAssertPointer(numCols, 7);
7848c789d87fSToby Isaac   if (indices) PetscAssertPointer(indices, 8);
7849c789d87fSToby Isaac   if (outOffsets) PetscAssertPointer(outOffsets, 9);
7850c789d87fSToby Isaac   if (values) PetscAssertPointer(values, 10);
78519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
785263a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
78539566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
785471f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
785507218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7856c459fbc1SJed Brown   if (useClPerm) {
7857c459fbc1SJed Brown     PetscInt depth, clsize;
78589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7859c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7860c459fbc1SJed Brown       PetscInt dof;
78619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7862c459fbc1SJed Brown       clsize += dof;
7863c459fbc1SJed Brown     }
78649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7865c459fbc1SJed Brown   }
786671f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
786771f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
78687773e69fSMatthew G. Knepley     PetscInt dof, fdof;
78697773e69fSMatthew G. Knepley 
78709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
78717773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
78729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
78737773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
78747773e69fSMatthew G. Knepley     }
787571f0bbf9SMatthew G. Knepley     Ni += dof;
78767773e69fSMatthew G. Knepley   }
7877c789d87fSToby Isaac   if (*numRows == -1) *numRows = Ni;
7878c789d87fSToby Isaac   if (*numCols == -1) *numCols = Ni;
7879c789d87fSToby Isaac   nRows = *numRows;
7880c789d87fSToby Isaac   nCols = *numCols;
78817773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
78821dca8a05SBarry 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);
788371f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
7884c789d87fSToby Isaac   if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols);
7885c789d87fSToby Isaac   if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows);
788671f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
78879566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
78889566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
788971f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
789071f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
789171f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
78926ecaa68aSToby Isaac 
789371f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
789471f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
789571f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
789671f0bbf9SMatthew G. Knepley 
78979566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
78989566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
789971f0bbf9SMatthew G. Knepley         if (flip) {
790071f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
790171f0bbf9SMatthew G. Knepley 
790271f0bbf9SMatthew G. Knepley           if (!valCopy) {
79039566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
790471f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
790571f0bbf9SMatthew G. Knepley             *values = valCopy;
790671f0bbf9SMatthew G. Knepley           }
790771f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
790871f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
790971f0bbf9SMatthew G. Knepley 
7910c789d87fSToby Isaac             if (multiplyRight) {
7911c789d87fSToby Isaac               for (k = 0; k < nRows; ++k) { valCopy[Ni * k + (foffset + i)] *= fval; }
7912c789d87fSToby Isaac             }
7913c789d87fSToby Isaac             if (multiplyLeft) {
7914c789d87fSToby Isaac               for (k = 0; k < nCols; ++k) { valCopy[nCols * (foffset + i) + k] *= fval; }
79156ecaa68aSToby Isaac             }
79166ecaa68aSToby Isaac           }
791771f0bbf9SMatthew G. Knepley         }
791871f0bbf9SMatthew G. Knepley         foffset += fdof;
791971f0bbf9SMatthew G. Knepley       }
792071f0bbf9SMatthew G. Knepley     }
792171f0bbf9SMatthew G. Knepley   }
792271f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
7923c789d87fSToby Isaac   PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft));
792471f0bbf9SMatthew G. Knepley   if (NclC) {
7925c789d87fSToby Isaac     if (multiplyRight) { *numCols = nCols = NiC; }
7926c789d87fSToby Isaac     if (multiplyLeft) { *numRows = nRows = NiC; }
79279566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
792871f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
79299566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
79309566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
793171f0bbf9SMatthew G. Knepley     }
793271f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
79339566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
79349566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
793571f0bbf9SMatthew G. Knepley     }
79369566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
793771f0bbf9SMatthew G. Knepley     Ncl    = NclC;
793871f0bbf9SMatthew G. Knepley     Ni     = NiC;
793971f0bbf9SMatthew G. Knepley     points = pointsC;
794071f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
794171f0bbf9SMatthew G. Knepley   }
794271f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
79439566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
79447caea556SToby Isaac   PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd));
794571f0bbf9SMatthew G. Knepley   if (Nf) {
794671f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
794771f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
794871f0bbf9SMatthew G. Knepley 
79499371c9d4SSatish Balay     if (outOffsets) {
79509371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
79519371c9d4SSatish Balay     }
79529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
795371f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
795471f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
795571f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
795671f0bbf9SMatthew G. Knepley 
79579566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
79587773e69fSMatthew G. Knepley       }
79597773e69fSMatthew G. Knepley     } else {
796071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
796171f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
796271f0bbf9SMatthew G. Knepley 
79637caea556SToby Isaac         if (pnt < idxStart || pnt >= idxEnd) continue;
79649566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
796571f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
796671f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
796771f0bbf9SMatthew G. Knepley          * global section. */
79689566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
796971f0bbf9SMatthew G. Knepley       }
797071f0bbf9SMatthew G. Knepley     }
797171f0bbf9SMatthew G. Knepley   } else {
797271f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
797371f0bbf9SMatthew G. Knepley 
797471f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
797571f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
79764acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
79774acb8e1eSToby Isaac 
79787caea556SToby Isaac       if (pnt < idxStart || pnt >= idxEnd) continue;
79799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
798071f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
798171f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
79829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
79837773e69fSMatthew G. Knepley     }
79847773e69fSMatthew G. Knepley   }
798571f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
798671f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
79879566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
79889566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
79894acb8e1eSToby Isaac   }
799071f0bbf9SMatthew G. Knepley   if (NclC) {
79919566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
79927773e69fSMatthew G. Knepley   } else {
79939566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
79947773e69fSMatthew G. Knepley   }
799571f0bbf9SMatthew G. Knepley 
799671f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
79973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79987773e69fSMatthew G. Knepley }
79997773e69fSMatthew G. Knepley 
8000d3d1a6afSToby Isaac /*@C
8001d3d1a6afSToby Isaac   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
8002d3d1a6afSToby Isaac 
8003d3d1a6afSToby Isaac   Not collective
8004d3d1a6afSToby Isaac 
8005d3d1a6afSToby Isaac   Input Parameters:
8006d3d1a6afSToby Isaac + dm         - The `DM`
8007d3d1a6afSToby Isaac . section    - The `PetscSection` describing the points (a local section)
8008d3d1a6afSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
8009d3d1a6afSToby Isaac . point      - The point defining the closure
8010d3d1a6afSToby Isaac - useClPerm  - Use the closure point permutation if available
8011d3d1a6afSToby Isaac 
8012d3d1a6afSToby Isaac   Output Parameters:
8013d3d1a6afSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections
8014d3d1a6afSToby Isaac . indices    - The dof indices
8015d3d1a6afSToby Isaac . outOffsets - Array to write the field offsets into, or `NULL`
8016d3d1a6afSToby Isaac - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
8017d3d1a6afSToby Isaac 
8018d3d1a6afSToby Isaac   Level: advanced
8019d3d1a6afSToby Isaac 
8020d3d1a6afSToby Isaac   Notes:
8021d3d1a6afSToby Isaac   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
8022d3d1a6afSToby Isaac 
8023d3d1a6afSToby Isaac   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
8024d3d1a6afSToby Isaac   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
8025d3d1a6afSToby Isaac   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
8026d3d1a6afSToby Isaac   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
8027d3d1a6afSToby Isaac   indices (with the above semantics) are implied.
8028d3d1a6afSToby Isaac 
8029d3d1a6afSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
8030d3d1a6afSToby Isaac           `PetscSection`, `DMGetGlobalSection()`
8031d3d1a6afSToby Isaac @*/
8032d3d1a6afSToby Isaac PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8033d3d1a6afSToby Isaac {
8034c789d87fSToby Isaac   PetscInt numRows = -1, numCols = -1;
8035d3d1a6afSToby Isaac 
8036d3d1a6afSToby Isaac   PetscFunctionBeginHot;
8037c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE));
8038c789d87fSToby Isaac   PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols);
8039c789d87fSToby Isaac   *numIndices = numRows;
80407773e69fSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
80417773e69fSMatthew G. Knepley }
80427773e69fSMatthew G. Knepley 
80437cd05799SMatthew G. Knepley /*@C
804471f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
80457cd05799SMatthew G. Knepley 
80467cd05799SMatthew G. Knepley   Not collective
80477cd05799SMatthew G. Knepley 
80487cd05799SMatthew G. Knepley   Input Parameters:
8049a1cb98faSBarry Smith + dm         - The `DM`
8050a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
8051a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
805271f0bbf9SMatthew G. Knepley . point      - The point defining the closure
805371f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
805471f0bbf9SMatthew G. Knepley 
805571f0bbf9SMatthew G. Knepley   Output Parameters:
805671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
805771f0bbf9SMatthew G. Knepley . indices    - The dof indices
805820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
805920f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
806071f0bbf9SMatthew G. Knepley 
8061a1cb98faSBarry Smith   Level: advanced
806271f0bbf9SMatthew G. Knepley 
8063a1cb98faSBarry Smith   Notes:
8064a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
8065a1cb98faSBarry Smith 
8066a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
806771f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
806871f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
806971f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
807071f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
80717cd05799SMatthew G. Knepley 
80721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
80737cd05799SMatthew G. Knepley @*/
8074d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8075d71ae5a4SJacob Faibussowitsch {
80767773e69fSMatthew G. Knepley   PetscFunctionBegin;
80777773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80784f572ea9SToby Isaac   PetscAssertPointer(indices, 7);
80799566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
80803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80817773e69fSMatthew G. Knepley }
80827773e69fSMatthew G. Knepley 
8083e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8084d71ae5a4SJacob Faibussowitsch {
8085552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
8086552f7358SJed Brown   PetscInt          *indices;
808771f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
808871f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
8089552f7358SJed Brown   PetscErrorCode     ierr;
8090552f7358SJed Brown 
8091552f7358SJed Brown   PetscFunctionBegin;
8092552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80939566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
80943dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
80959566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
80963dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
8097e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 5);
8098552f7358SJed Brown 
8099e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values));
81000d644c17SKarl Rupp 
81019566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
8102d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
81034a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
8104552f7358SJed Brown   if (ierr) {
8105552f7358SJed Brown     PetscMPIInt rank;
8106552f7358SJed Brown 
81079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81089566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81099566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
81109566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81119566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
8112c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
8113552f7358SJed Brown   }
81144a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
81154a1e0b3eSMatthew G. Knepley     PetscInt i;
81169566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
811763a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
81189566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
81194a1e0b3eSMatthew G. Knepley   }
812071f0bbf9SMatthew G. Knepley 
81219566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81229566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
81233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81244acb8e1eSToby Isaac }
812571f0bbf9SMatthew G. Knepley 
81264a1e0b3eSMatthew G. Knepley /*@C
8127e8e188d2SZach Atkins   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
8128e8e188d2SZach Atkins 
8129e8e188d2SZach Atkins   Not collective
8130e8e188d2SZach Atkins 
8131e8e188d2SZach Atkins   Input Parameters:
8132e8e188d2SZach Atkins + dm            - The `DM`
8133e8e188d2SZach Atkins . section       - The section describing the layout in `v`, or `NULL` to use the default section
8134e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
8135e8e188d2SZach Atkins . A             - The matrix
8136e8e188d2SZach Atkins . point         - The point in the `DM`
8137e8e188d2SZach Atkins . values        - The array of values
8138e8e188d2SZach Atkins - mode          - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
8139e8e188d2SZach Atkins 
8140e8e188d2SZach Atkins   Level: intermediate
8141e8e188d2SZach Atkins 
8142e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
8143e8e188d2SZach Atkins @*/
8144e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8145e8e188d2SZach Atkins {
8146e8e188d2SZach Atkins   PetscFunctionBegin;
8147e8e188d2SZach Atkins   PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode));
8148e8e188d2SZach Atkins   PetscFunctionReturn(PETSC_SUCCESS);
8149e8e188d2SZach Atkins }
8150e8e188d2SZach Atkins 
8151e8e188d2SZach Atkins /*@C
815260225df5SJacob Faibussowitsch   DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section
81534a1e0b3eSMatthew G. Knepley 
81544a1e0b3eSMatthew G. Knepley   Not collective
81554a1e0b3eSMatthew G. Knepley 
81564a1e0b3eSMatthew G. Knepley   Input Parameters:
8157a1cb98faSBarry Smith + dmRow            - The `DM` for the row fields
815820f4b53cSBarry Smith . sectionRow       - The section describing the layout, or `NULL` to use the default section in `dmRow`
8159e8e188d2SZach Atkins . useRowPerm       - The flag to use the closure permutation of the `dmRow` if available
816020f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
8161a1cb98faSBarry Smith . dmCol            - The `DM` for the column fields
816220f4b53cSBarry Smith . sectionCol       - The section describing the layout, or `NULL` to use the default section in `dmCol`
8163e8e188d2SZach Atkins . useColPerm       - The flag to use the closure permutation of the `dmCol` if available
816420f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
81654a1e0b3eSMatthew G. Knepley . A                - The matrix
8166a1cb98faSBarry Smith . point            - The point in the `DM`
81674a1e0b3eSMatthew G. Knepley . values           - The array of values
8168a1cb98faSBarry Smith - mode             - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
81694a1e0b3eSMatthew G. Knepley 
81704a1e0b3eSMatthew G. Knepley   Level: intermediate
81714a1e0b3eSMatthew G. Knepley 
81721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
81734a1e0b3eSMatthew G. Knepley @*/
8174e8e188d2SZach 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)
8175d71ae5a4SJacob Faibussowitsch {
817671f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
817771f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
8178c789d87fSToby Isaac   PetscInt           numIndicesRow = -1, numIndicesCol = -1;
81797caea556SToby Isaac   const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2;
8180c789d87fSToby Isaac 
818171f0bbf9SMatthew G. Knepley   PetscErrorCode ierr;
818271f0bbf9SMatthew G. Knepley 
818371f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
818471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
81859566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
818671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
81879566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
818871f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
8189e8e188d2SZach Atkins   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5);
81909566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
8191e8e188d2SZach Atkins   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6);
81929566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
8193e8e188d2SZach Atkins   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7);
8194e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 9);
819571f0bbf9SMatthew G. Knepley 
8196c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow));
8197c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol));
81987caea556SToby Isaac   valuesV1 = valuesV0;
8199c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE));
82007caea556SToby Isaac   valuesV2 = valuesV1;
8201c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE));
820271f0bbf9SMatthew G. Knepley 
8203c789d87fSToby Isaac   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2));
8204d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8205c789d87fSToby Isaac   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode);
820671f0bbf9SMatthew G. Knepley   if (ierr) {
820771f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
820871f0bbf9SMatthew G. Knepley 
82099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
82109566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
82119566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
82127caea556SToby Isaac     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2));
82137caea556SToby Isaac     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1));
82147caea556SToby Isaac     if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2));
82157caea556SToby Isaac     if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1));
8216d3d1a6afSToby Isaac   }
821771f0bbf9SMatthew G. Knepley 
82187caea556SToby Isaac   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2));
82197caea556SToby Isaac   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1));
82207caea556SToby Isaac   if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2));
82217caea556SToby Isaac   if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1));
82223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8223552f7358SJed Brown }
8224552f7358SJed Brown 
8225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8226d71ae5a4SJacob Faibussowitsch {
8227de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
8228de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
8229de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
8230de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
823117c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8232de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
8233412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
82344ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
8235de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
8236de41b84cSMatthew G. Knepley 
8237de41b84cSMatthew G. Knepley   PetscFunctionBegin;
8238de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
8239de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
82409566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
8241de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
82429566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
8243de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
82449566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
8245de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
82469566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
8247de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
8248de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
82499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
825063a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
82519566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
82529566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
8253de41b84cSMatthew G. Knepley   /* Column indices */
82549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
82554ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
8256de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
8257de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
82589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8259de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8260de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8261de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8262de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8263de41b84cSMatthew G. Knepley       ++q;
8264de41b84cSMatthew G. Knepley     }
8265de41b84cSMatthew G. Knepley   }
8266de41b84cSMatthew G. Knepley   numCPoints = q;
8267de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8268de41b84cSMatthew G. Knepley     PetscInt fdof;
8269de41b84cSMatthew G. Knepley 
82709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
82714ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8272de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
82739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8274de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8275de41b84cSMatthew G. Knepley     }
8276de41b84cSMatthew G. Knepley     numCIndices += dof;
8277de41b84cSMatthew G. Knepley   }
8278de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8279de41b84cSMatthew G. Knepley   /* Row indices */
82809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8281412e9a14SMatthew G. Knepley   {
8282012bc364SMatthew G. Knepley     DMPlexTransform tr;
8283012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8284012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8285012bc364SMatthew G. Knepley 
82869566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
82879566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
82889566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8289012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
82909566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8291412e9a14SMatthew G. Knepley   }
82929566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8293de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8294de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
82959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8296de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
82979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8298de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8299de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
83009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
83014ca5e9f5SMatthew G. Knepley         if (!dof) continue;
83029371c9d4SSatish Balay         for (s = 0; s < q; ++s)
83039371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
83044ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8305de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8306de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8307de41b84cSMatthew G. Knepley         ++q;
8308de41b84cSMatthew G. Knepley       }
8309de41b84cSMatthew G. Knepley     }
83109566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8311de41b84cSMatthew G. Knepley   }
8312de41b84cSMatthew G. Knepley   numFPoints = q;
8313de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8314de41b84cSMatthew G. Knepley     PetscInt fdof;
8315de41b84cSMatthew G. Knepley 
83169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
83174ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8318de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8320de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8321de41b84cSMatthew G. Knepley     }
8322de41b84cSMatthew G. Knepley     numFIndices += dof;
8323de41b84cSMatthew G. Knepley   }
8324de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8325de41b84cSMatthew G. Knepley 
83261dca8a05SBarry 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);
83271dca8a05SBarry 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);
83289566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83299566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8330de41b84cSMatthew G. Knepley   if (numFields) {
83314acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
83324acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
83334acb8e1eSToby Isaac 
83344acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
83359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
83369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8337de41b84cSMatthew G. Knepley     }
83384acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
83399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
83409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
83414acb8e1eSToby Isaac     }
83424acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
83439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
83449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
83454acb8e1eSToby Isaac     }
83464acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
83479566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
83489566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8349de41b84cSMatthew G. Knepley     }
8350de41b84cSMatthew G. Knepley   } else {
83514acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
83524acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
83534acb8e1eSToby Isaac 
83549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
83559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
83564acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
83574acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
83584acb8e1eSToby Isaac 
83599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
83609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8361de41b84cSMatthew G. Knepley     }
83624acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
83634acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
83644acb8e1eSToby Isaac 
83659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
83669566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8367de41b84cSMatthew G. Knepley     }
83689566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
83699566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8370de41b84cSMatthew G. Knepley   }
83719566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
83724acb8e1eSToby Isaac   /* TODO: flips */
8373d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8374de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8375de41b84cSMatthew G. Knepley   if (ierr) {
8376de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8377de41b84cSMatthew G. Knepley 
83789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
83799566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
83809566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
83819566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83829566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8383de41b84cSMatthew G. Knepley   }
83849566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
83859566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
83869566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83879566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
83883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8389de41b84cSMatthew G. Knepley }
8390de41b84cSMatthew G. Knepley 
8391d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8392d71ae5a4SJacob Faibussowitsch {
83937c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
83947c927364SMatthew G. Knepley   PetscInt       *cpoints      = NULL;
8395230af79eSStefano Zampini   PetscInt        foffsets[32] = {0}, coffsets[32] = {0};
839617c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8397412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
83987c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
83997c927364SMatthew G. Knepley 
84007c927364SMatthew G. Knepley   PetscFunctionBegin;
84017c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
84027c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
84039566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
84047c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
84059566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
84067c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
84079566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
84087c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
84099566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
84107c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
84119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
841263a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
84137c927364SMatthew G. Knepley   /* Column indices */
84149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84157c927364SMatthew G. Knepley   maxFPoints = numCPoints;
84167c927364SMatthew G. Knepley   /* Compress out points not in the section */
84177c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
84189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
84197c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
84207c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
84217c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
84227c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
84237c927364SMatthew G. Knepley       ++q;
84247c927364SMatthew G. Knepley     }
84257c927364SMatthew G. Knepley   }
84267c927364SMatthew G. Knepley   numCPoints = q;
84277c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
84287c927364SMatthew G. Knepley     PetscInt fdof;
84297c927364SMatthew G. Knepley 
84309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
84317c927364SMatthew G. Knepley     if (!dof) continue;
84327c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
84339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
84347c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
84357c927364SMatthew G. Knepley     }
84367c927364SMatthew G. Knepley     numCIndices += dof;
84377c927364SMatthew G. Knepley   }
84387c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
84397c927364SMatthew G. Knepley   /* Row indices */
84409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8441412e9a14SMatthew G. Knepley   {
8442012bc364SMatthew G. Knepley     DMPlexTransform tr;
8443012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8444012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8445012bc364SMatthew G. Knepley 
84469566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
84479566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
84489566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8449012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
84509566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8451412e9a14SMatthew G. Knepley   }
84529566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
84537c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
84547c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
84559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
84567c927364SMatthew G. Knepley     /* Compress out points not in the section */
84579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
84587c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
84597c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
84609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
84617c927364SMatthew G. Knepley         if (!dof) continue;
84629371c9d4SSatish Balay         for (s = 0; s < q; ++s)
84639371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
84647c927364SMatthew G. Knepley         if (s < q) continue;
84657c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
84667c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
84677c927364SMatthew G. Knepley         ++q;
84687c927364SMatthew G. Knepley       }
84697c927364SMatthew G. Knepley     }
84709566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
84717c927364SMatthew G. Knepley   }
84727c927364SMatthew G. Knepley   numFPoints = q;
84737c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
84747c927364SMatthew G. Knepley     PetscInt fdof;
84757c927364SMatthew G. Knepley 
84769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
84777c927364SMatthew G. Knepley     if (!dof) continue;
84787c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
84799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
84807c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
84817c927364SMatthew G. Knepley     }
84827c927364SMatthew G. Knepley     numFIndices += dof;
84837c927364SMatthew G. Knepley   }
84847c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
84857c927364SMatthew G. Knepley 
84861dca8a05SBarry 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);
84871dca8a05SBarry 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);
84887c927364SMatthew G. Knepley   if (numFields) {
84894acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
84904acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
84914acb8e1eSToby Isaac 
84924acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
84957c927364SMatthew G. Knepley     }
84964acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
84979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
84994acb8e1eSToby Isaac     }
85004acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
85019566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85029566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
85034acb8e1eSToby Isaac     }
85044acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
85059566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
85069566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
85077c927364SMatthew G. Knepley     }
85087c927364SMatthew G. Knepley   } else {
85094acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
85104acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
85114acb8e1eSToby Isaac 
85129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85144acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
85154acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
85164acb8e1eSToby Isaac 
85179566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
85189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
85197c927364SMatthew G. Knepley     }
85204acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
85214acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
85224acb8e1eSToby Isaac 
85239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
85257c927364SMatthew G. Knepley     }
85269566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85279566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85287c927364SMatthew G. Knepley   }
85299566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
85309566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
85313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85327c927364SMatthew G. Knepley }
85337c927364SMatthew G. Knepley 
85347cd05799SMatthew G. Knepley /*@C
85357cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
85367cd05799SMatthew G. Knepley 
85377cd05799SMatthew G. Knepley   Input Parameter:
8538a1cb98faSBarry Smith . dm - The `DMPLEX` object
85397cd05799SMatthew G. Knepley 
85407cd05799SMatthew G. Knepley   Output Parameter:
85417cd05799SMatthew G. Knepley . cellHeight - The height of a cell
85427cd05799SMatthew G. Knepley 
85437cd05799SMatthew G. Knepley   Level: developer
85447cd05799SMatthew G. Knepley 
85451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
85467cd05799SMatthew G. Knepley @*/
8547d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8548d71ae5a4SJacob Faibussowitsch {
8549552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8550552f7358SJed Brown 
8551552f7358SJed Brown   PetscFunctionBegin;
8552552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85534f572ea9SToby Isaac   PetscAssertPointer(cellHeight, 2);
8554552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
85553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8556552f7358SJed Brown }
8557552f7358SJed Brown 
85587cd05799SMatthew G. Knepley /*@C
85597cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
85607cd05799SMatthew G. Knepley 
85617cd05799SMatthew G. Knepley   Input Parameters:
8562a1cb98faSBarry Smith + dm         - The `DMPLEX` object
85637cd05799SMatthew G. Knepley - cellHeight - The height of a cell
85647cd05799SMatthew G. Knepley 
85657cd05799SMatthew G. Knepley   Level: developer
85667cd05799SMatthew G. Knepley 
85671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
85687cd05799SMatthew G. Knepley @*/
8569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8570d71ae5a4SJacob Faibussowitsch {
8571552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8572552f7358SJed Brown 
8573552f7358SJed Brown   PetscFunctionBegin;
8574552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8575552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
85763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8577552f7358SJed Brown }
8578552f7358SJed Brown 
8579e6139122SMatthew G. Knepley /*@
85802827ebadSStefano Zampini   DMPlexGetCellTypeStratum - Get the range of cells of a given celltype
8581e6139122SMatthew G. Knepley 
85822827ebadSStefano Zampini   Input Parameters:
85832827ebadSStefano Zampini + dm - The `DMPLEX` object
85842827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell
8585e6139122SMatthew G. Knepley 
8586e6139122SMatthew G. Knepley   Output Parameters:
85872827ebadSStefano Zampini + start - The first cell of this type, or `NULL`
85882827ebadSStefano Zampini - end   - The upper bound on this celltype, or `NULL`
8589e6139122SMatthew G. Knepley 
85902a9f31c0SMatthew G. Knepley   Level: advanced
8591e6139122SMatthew G. Knepley 
85922827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
8593e6139122SMatthew G. Knepley @*/
85942827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end)
8595d71ae5a4SJacob Faibussowitsch {
85962827ebadSStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
85972827ebadSStefano Zampini   DMLabel  label;
85982827ebadSStefano Zampini   PetscInt pStart, pEnd;
8599e6139122SMatthew G. Knepley 
8600e6139122SMatthew G. Knepley   PetscFunctionBegin;
8601e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86022827ebadSStefano Zampini   if (start) {
86034f572ea9SToby Isaac     PetscAssertPointer(start, 3);
86042827ebadSStefano Zampini     *start = 0;
86052827ebadSStefano Zampini   }
86062827ebadSStefano Zampini   if (end) {
86074f572ea9SToby Isaac     PetscAssertPointer(end, 4);
86082827ebadSStefano Zampini     *end = 0;
86092827ebadSStefano Zampini   }
86102827ebadSStefano Zampini   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
86112827ebadSStefano Zampini   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
86122827ebadSStefano Zampini   if (mesh->tr) {
86132827ebadSStefano Zampini     PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end));
86142827ebadSStefano Zampini   } else {
86152827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
86162827ebadSStefano Zampini     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found");
86172827ebadSStefano Zampini     PetscCall(DMLabelGetStratumBounds(label, ct, start, end));
86182827ebadSStefano Zampini   }
86193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8620e6139122SMatthew G. Knepley }
8621e6139122SMatthew G. Knepley 
8622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8623d71ae5a4SJacob Faibussowitsch {
8624552f7358SJed Brown   PetscSection section, globalSection;
8625552f7358SJed Brown   PetscInt    *numbers, p;
8626552f7358SJed Brown 
8627552f7358SJed Brown   PetscFunctionBegin;
8628d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
86299566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
86309566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
863148a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
86329566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
8633eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection));
86349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8635552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
86369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8637ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8638ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8639552f7358SJed Brown   }
86409566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8641ef48cebcSMatthew G. Knepley   if (globalSize) {
8642ef48cebcSMatthew G. Knepley     PetscLayout layout;
86439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
86449566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
86459566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8646ef48cebcSMatthew G. Knepley   }
86479566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
86489566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
86493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8650552f7358SJed Brown }
8651552f7358SJed Brown 
8652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8653d71ae5a4SJacob Faibussowitsch {
8654412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8655552f7358SJed Brown 
8656552f7358SJed Brown   PetscFunctionBegin;
86579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
86589566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
86599566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
86609566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
86613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8662552f7358SJed Brown }
866381ed3555SMatthew G. Knepley 
86648dab3259SMatthew G. Knepley /*@
86657cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
86667cd05799SMatthew G. Knepley 
86677cd05799SMatthew G. Knepley   Input Parameter:
8668a1cb98faSBarry Smith . dm - The `DMPLEX` object
86697cd05799SMatthew G. Knepley 
86707cd05799SMatthew G. Knepley   Output Parameter:
86717cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
86727cd05799SMatthew G. Knepley 
86737cd05799SMatthew G. Knepley   Level: developer
86747cd05799SMatthew G. Knepley 
86751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
86767cd05799SMatthew G. Knepley @*/
8677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8678d71ae5a4SJacob Faibussowitsch {
867981ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
868081ed3555SMatthew G. Knepley 
868181ed3555SMatthew G. Knepley   PetscFunctionBegin;
868281ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86839566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8684552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
86853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8686552f7358SJed Brown }
8687552f7358SJed Brown 
8688d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8689d71ae5a4SJacob Faibussowitsch {
8690412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
869181ed3555SMatthew G. Knepley 
869281ed3555SMatthew G. Knepley   PetscFunctionBegin;
869381ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
86959566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
86963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
869781ed3555SMatthew G. Knepley }
869881ed3555SMatthew G. Knepley 
86998dab3259SMatthew G. Knepley /*@
87006aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
87017cd05799SMatthew G. Knepley 
87027cd05799SMatthew G. Knepley   Input Parameter:
8703a1cb98faSBarry Smith . dm - The `DMPLEX` object
87047cd05799SMatthew G. Knepley 
87057cd05799SMatthew G. Knepley   Output Parameter:
87067cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
87077cd05799SMatthew G. Knepley 
87087cd05799SMatthew G. Knepley   Level: developer
87097cd05799SMatthew G. Knepley 
87101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87117cd05799SMatthew G. Knepley @*/
8712d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8713d71ae5a4SJacob Faibussowitsch {
8714552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8715552f7358SJed Brown 
8716552f7358SJed Brown   PetscFunctionBegin;
8717552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87189566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8719552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
87203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8721552f7358SJed Brown }
8722552f7358SJed Brown 
87238dab3259SMatthew G. Knepley /*@
8724966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8725966484cfSJed Brown 
872620f4b53cSBarry Smith   Collective
87277cd05799SMatthew G. Knepley 
87287cd05799SMatthew G. Knepley   Input Parameter:
8729a1cb98faSBarry Smith . dm - The `DMPLEX` object
87307cd05799SMatthew G. Knepley 
87317cd05799SMatthew G. Knepley   Output Parameter:
87327cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
87337cd05799SMatthew G. Knepley 
8734a1cb98faSBarry Smith   Level: developer
8735966484cfSJed Brown 
8736a1cb98faSBarry Smith   Notes:
8737a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8738966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8739966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8740966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8741966484cfSJed Brown 
8742966484cfSJed Brown   The partitioned mesh is
8743966484cfSJed Brown   ```
8744966484cfSJed Brown   (2)--0--(3)--1--(4)    (1)--0--(2)
8745966484cfSJed Brown   ```
8746966484cfSJed Brown   and its global numbering is
8747966484cfSJed Brown   ```
8748966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8749966484cfSJed Brown   ```
8750966484cfSJed Brown   Then the global numbering is provided as
8751966484cfSJed Brown   ```
8752966484cfSJed Brown   [0] Number of indices in set 5
8753966484cfSJed Brown   [0] 0 0
8754966484cfSJed Brown   [0] 1 1
8755966484cfSJed Brown   [0] 2 3
8756966484cfSJed Brown   [0] 3 4
8757966484cfSJed Brown   [0] 4 -6
8758966484cfSJed Brown   [1] Number of indices in set 3
8759966484cfSJed Brown   [1] 0 2
8760966484cfSJed Brown   [1] 1 5
8761966484cfSJed Brown   [1] 2 6
8762966484cfSJed Brown   ```
8763966484cfSJed Brown 
87641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87657cd05799SMatthew G. Knepley @*/
8766d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8767d71ae5a4SJacob Faibussowitsch {
8768ef48cebcSMatthew G. Knepley   IS        nums[4];
8769862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8770ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
87710c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8772ef48cebcSMatthew G. Knepley 
8773ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8774ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
87760c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
87779566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
87780c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8779862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8780862913ffSStefano Zampini     PetscInt end;
8781862913ffSStefano Zampini 
8782862913ffSStefano Zampini     depths[d] = depth - d;
87839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
87840c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8785862913ffSStefano Zampini   }
87860c15888dSMatthew G. Knepley   if (empty)
87870c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
87880c15888dSMatthew G. Knepley       depths[d] = -1;
87890c15888dSMatthew G. Knepley       starts[d] = -1;
87900c15888dSMatthew G. Knepley     }
87910c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
87921c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8793ad540459SPierre 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]);
87940c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8795ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8796ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8797ef48cebcSMatthew G. Knepley 
87989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
87999566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8800ef48cebcSMatthew G. Knepley     shift += gsize;
8801ef48cebcSMatthew G. Knepley   }
8802d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
88039566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
88043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8805ef48cebcSMatthew G. Knepley }
8806ef48cebcSMatthew G. Knepley 
880708a22f4bSMatthew G. Knepley /*@
880808a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
880908a22f4bSMatthew G. Knepley 
881008a22f4bSMatthew G. Knepley   Input Parameter:
8811a1cb98faSBarry Smith . dm - The `DMPLEX` object
881208a22f4bSMatthew G. Knepley 
881308a22f4bSMatthew G. Knepley   Output Parameter:
881408a22f4bSMatthew G. Knepley . ranks - The rank field
881508a22f4bSMatthew G. Knepley 
8816a1cb98faSBarry Smith   Options Database Key:
881720f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
881808a22f4bSMatthew G. Knepley 
881908a22f4bSMatthew G. Knepley   Level: intermediate
882008a22f4bSMatthew G. Knepley 
88211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
882208a22f4bSMatthew G. Knepley @*/
8823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8824d71ae5a4SJacob Faibussowitsch {
882508a22f4bSMatthew G. Knepley   DM             rdm;
882608a22f4bSMatthew G. Knepley   PetscFE        fe;
882708a22f4bSMatthew G. Knepley   PetscScalar   *r;
882808a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8829a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
883008a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8831a55f9a55SMatthew G. Knepley   PetscBool      simplex;
883208a22f4bSMatthew G. Knepley 
883308a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8834f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88354f572ea9SToby Isaac   PetscAssertPointer(ranks, 2);
88369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
88379566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
88389566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
88399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
88409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8841a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
88429566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
88439566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
88449566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
88459566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
88469566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
88479566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
88489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
88499566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
885008a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
885108a22f4bSMatthew G. Knepley     PetscScalar *lr;
885208a22f4bSMatthew G. Knepley 
88539566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
885471f09efeSPierre Jolivet     if (lr) *lr = rank;
885508a22f4bSMatthew G. Knepley   }
88569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
88579566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
88583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
885908a22f4bSMatthew G. Knepley }
886008a22f4bSMatthew G. Knepley 
8861ca8062c8SMatthew G. Knepley /*@
8862acf3173eSStefano Zampini   DMPlexCreateLabelField - Create a field whose value is the label value for that point
886318e14f0cSMatthew G. Knepley 
886418e14f0cSMatthew G. Knepley   Input Parameters:
886520f4b53cSBarry Smith + dm    - The `DMPLEX`
886620f4b53cSBarry Smith - label - The `DMLabel`
886718e14f0cSMatthew G. Knepley 
886818e14f0cSMatthew G. Knepley   Output Parameter:
886918e14f0cSMatthew G. Knepley . val - The label value field
887018e14f0cSMatthew G. Knepley 
887120f4b53cSBarry Smith   Options Database Key:
887220f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
887318e14f0cSMatthew G. Knepley 
887418e14f0cSMatthew G. Knepley   Level: intermediate
887518e14f0cSMatthew G. Knepley 
88761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
887718e14f0cSMatthew G. Knepley @*/
8878d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8879d71ae5a4SJacob Faibussowitsch {
88801033741fSStefano Zampini   DM             rdm, plex;
8881acf3173eSStefano Zampini   Vec            lval;
8882acf3173eSStefano Zampini   PetscSection   section;
888318e14f0cSMatthew G. Knepley   PetscFE        fe;
888418e14f0cSMatthew G. Knepley   PetscScalar   *v;
8885acf3173eSStefano Zampini   PetscInt       dim, pStart, pEnd, p, cStart;
8886acf3173eSStefano Zampini   DMPolytopeType ct;
8887acf3173eSStefano Zampini   char           name[PETSC_MAX_PATH_LEN];
8888acf3173eSStefano Zampini   const char    *lname, *prefix;
888918e14f0cSMatthew G. Knepley 
889018e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
889118e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88924f572ea9SToby Isaac   PetscAssertPointer(label, 2);
88934f572ea9SToby Isaac   PetscAssertPointer(val, 3);
88949566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
8895acf3173eSStefano Zampini   PetscCall(DMConvert(rdm, DMPLEX, &plex));
8896acf3173eSStefano Zampini   PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL));
8897acf3173eSStefano Zampini   PetscCall(DMPlexGetCellType(plex, cStart, &ct));
8898acf3173eSStefano Zampini   PetscCall(DMDestroy(&plex));
88999566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
8900acf3173eSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
8901acf3173eSStefano Zampini   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
8902acf3173eSStefano Zampini   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname));
8903acf3173eSStefano Zampini   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe));
8904acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)fe, ""));
89059566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
89069566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
89079566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
89089566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
8909acf3173eSStefano Zampini   PetscCall(DMCreateLocalVector(rdm, &lval));
8910acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)*val, lname));
8911acf3173eSStefano Zampini   PetscCall(DMGetLocalSection(rdm, &section));
8912acf3173eSStefano Zampini   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
8913acf3173eSStefano Zampini   PetscCall(VecGetArray(lval, &v));
8914acf3173eSStefano Zampini   for (p = pStart; p < pEnd; ++p) {
8915acf3173eSStefano Zampini     PetscInt cval, dof, off;
891618e14f0cSMatthew G. Knepley 
8917acf3173eSStefano Zampini     PetscCall(PetscSectionGetDof(section, p, &dof));
8918acf3173eSStefano Zampini     if (!dof) continue;
8919acf3173eSStefano Zampini     PetscCall(DMLabelGetValue(label, p, &cval));
8920acf3173eSStefano Zampini     PetscCall(PetscSectionGetOffset(section, p, &off));
8921acf3173eSStefano Zampini     for (PetscInt d = 0; d < dof; d++) v[off + d] = cval;
892218e14f0cSMatthew G. Knepley   }
8923acf3173eSStefano Zampini   PetscCall(VecRestoreArray(lval, &v));
8924acf3173eSStefano Zampini   PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val));
8925acf3173eSStefano Zampini   PetscCall(VecDestroy(&lval));
89269566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
89273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
892818e14f0cSMatthew G. Knepley }
892918e14f0cSMatthew G. Knepley 
893018e14f0cSMatthew G. Knepley /*@
8931ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8932ca8062c8SMatthew G. Knepley 
893369916449SMatthew G. Knepley   Input Parameter:
8934a1cb98faSBarry Smith . dm - The `DMPLEX` object
8935a1cb98faSBarry Smith 
8936a1cb98faSBarry Smith   Level: developer
8937ca8062c8SMatthew G. Knepley 
893895eb5ee5SVaclav Hapla   Notes:
893995eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
894095eb5ee5SVaclav Hapla 
894120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8942ca8062c8SMatthew G. Knepley 
89431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8944ca8062c8SMatthew G. Knepley @*/
8945d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8946d71ae5a4SJacob Faibussowitsch {
8947ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8948ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8949ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
895057beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
895157beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8952ca8062c8SMatthew G. Knepley 
8953ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8954ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89559566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
89569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
89579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8958ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
89599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8960ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
89619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
89629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8963ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
896442e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
896542e66dfaSMatthew G. Knepley       PetscInt  d;
896642e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
89679371c9d4SSatish Balay         if (cone[c] == cone[d]) {
89689371c9d4SSatish Balay           dup = PETSC_TRUE;
89699371c9d4SSatish Balay           break;
89709371c9d4SSatish Balay         }
897142e66dfaSMatthew G. Knepley       }
89729566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
89739566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8974ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8975ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8976ca8062c8SMatthew G. Knepley       }
897742e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
897863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
897948a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
89809566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
898163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
898248a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
89839566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
898463a3b9bcSJacob 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]);
8985f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8986ca8062c8SMatthew G. Knepley       }
898742e66dfaSMatthew G. Knepley     }
89889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
89899371c9d4SSatish Balay     if (p != pp) {
89909371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
89919371c9d4SSatish Balay       continue;
89929371c9d4SSatish Balay     }
89939566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
89949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8995ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
89969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
89979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8998ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
89999566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
90009371c9d4SSatish Balay         if (cone[c] != pp) {
90019371c9d4SSatish Balay           c = 0;
90029371c9d4SSatish Balay           break;
90039371c9d4SSatish Balay         }
9004ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
9005ca8062c8SMatthew G. Knepley       }
9006ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
900763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
900848a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
90099566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
901063a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
901148a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
90129566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
901363a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
9014ca8062c8SMatthew G. Knepley       }
9015ca8062c8SMatthew G. Knepley     }
9016ca8062c8SMatthew G. Knepley   }
901757beb4faSStefano Zampini   if (storagecheck) {
90189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
90199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
902063a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
902157beb4faSStefano Zampini   }
90223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9023ca8062c8SMatthew G. Knepley }
9024ca8062c8SMatthew G. Knepley 
9025412e9a14SMatthew G. Knepley /*
9026412e9a14SMatthew 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.
9027412e9a14SMatthew G. Knepley */
9028d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
9029d71ae5a4SJacob Faibussowitsch {
9030412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
9031412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
9032412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
9033412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
9034412e9a14SMatthew G. Knepley 
9035412e9a14SMatthew G. Knepley   PetscFunctionBegin;
9036412e9a14SMatthew G. Knepley   *unsplit = 0;
9037412e9a14SMatthew G. Knepley   switch (ct) {
9038d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
9039d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
9040d71ae5a4SJacob Faibussowitsch     break;
9041412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
90429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
90439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9044412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
90459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
9046412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
9047412e9a14SMatthew G. Knepley     }
9048412e9a14SMatthew G. Knepley     break;
9049412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
9050412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
90519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
90529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9053412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
90549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
90559566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
9056412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
90579566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
9058412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
9059412e9a14SMatthew G. Knepley           PetscInt p;
90609371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
90619371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
9062412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
9063412e9a14SMatthew G. Knepley         }
9064412e9a14SMatthew G. Knepley       }
9065412e9a14SMatthew G. Knepley     }
9066412e9a14SMatthew G. Knepley     break;
9067d71ae5a4SJacob Faibussowitsch   default:
9068d71ae5a4SJacob Faibussowitsch     break;
9069412e9a14SMatthew G. Knepley   }
9070412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
90719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
9072412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
9073412e9a14SMatthew G. Knepley   }
90743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9075412e9a14SMatthew G. Knepley }
9076412e9a14SMatthew G. Knepley 
9077ca8062c8SMatthew G. Knepley /*@
9078ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
9079ca8062c8SMatthew G. Knepley 
9080ca8062c8SMatthew G. Knepley   Input Parameters:
9081a1cb98faSBarry Smith + dm         - The `DMPLEX` object
908258723a97SMatthew G. Knepley - cellHeight - Normally 0
9083ca8062c8SMatthew G. Knepley 
9084a1cb98faSBarry Smith   Level: developer
9085a1cb98faSBarry Smith 
908695eb5ee5SVaclav Hapla   Notes:
908795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
908825c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
9089ca8062c8SMatthew G. Knepley 
909020f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
909195eb5ee5SVaclav Hapla 
90921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9093ca8062c8SMatthew G. Knepley @*/
9094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
9095d71ae5a4SJacob Faibussowitsch {
9096412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
9097412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
9098412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
9099ca8062c8SMatthew G. Knepley 
9100ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9101ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91029566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
91039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
91049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9105412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9106412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
9107412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
910858723a97SMatthew G. Knepley 
91099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
911063a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
9111412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
9112412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
91139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
911463a3b9bcSJacob 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));
9115412e9a14SMatthew G. Knepley     }
91169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
911758723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
911858723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
9119412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
912058723a97SMatthew G. Knepley     }
91219566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
9122412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
9123412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
9124412e9a14SMatthew G. Knepley       PetscInt unsplit;
912542363296SMatthew G. Knepley 
91269566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9127412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
912842363296SMatthew G. Knepley     }
912963a3b9bcSJacob 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));
913042363296SMatthew G. Knepley   }
91313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9132ca8062c8SMatthew G. Knepley }
91339bf0dad6SMatthew G. Knepley 
91349bf0dad6SMatthew G. Knepley /*@
91359bf0dad6SMatthew 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
91369bf0dad6SMatthew G. Knepley 
913720f4b53cSBarry Smith   Collective
9138899ea2b8SJacob Faibussowitsch 
91399bf0dad6SMatthew G. Knepley   Input Parameters:
9140a1cb98faSBarry Smith + dm         - The `DMPLEX` object
91419bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
91429bf0dad6SMatthew G. Knepley 
9143a1cb98faSBarry Smith   Level: developer
9144a1cb98faSBarry Smith 
914545da879fSVaclav Hapla   Notes:
914645da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
914745da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
914845da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
914945da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
91509bf0dad6SMatthew G. Knepley 
9151a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
915295eb5ee5SVaclav Hapla 
91531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
91549bf0dad6SMatthew G. Knepley @*/
9155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
9156d71ae5a4SJacob Faibussowitsch {
9157ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
9158899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
91599bf0dad6SMatthew G. Knepley 
91609bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
91619bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91628f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
91633ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
91648f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
91653ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
91663ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9167899ea2b8SJacob Faibussowitsch   }
9168899ea2b8SJacob Faibussowitsch 
91699566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
91709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
91719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9172ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
91739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
91743554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
9175412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
9176412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
9177ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
9178412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
9179412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
91809bf0dad6SMatthew G. Knepley 
91819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
91829566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9183412e9a14SMatthew G. Knepley       if (unsplit) continue;
91849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
91859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
91869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
91879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
91889bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
91899bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
91909bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
91919bf0dad6SMatthew G. Knepley       }
91929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
919363a3b9bcSJacob 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);
91949bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
9195d4961f80SStefano Zampini         DMPolytopeType fct;
91969bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
91979bf0dad6SMatthew G. Knepley 
91989566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
91999566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
92009bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
92019bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
92029bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
92039bf0dad6SMatthew G. Knepley         }
920463a3b9bcSJacob 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]);
92059bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
9206b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
9207b5a892a1SMatthew G. Knepley             PetscInt v1;
9208b5a892a1SMatthew G. Knepley 
92099566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
921063a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
92119566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
921263a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
92139566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
921463a3b9bcSJacob 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]);
9215b5a892a1SMatthew G. Knepley           }
92169bf0dad6SMatthew G. Knepley         }
92179566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
9218412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
92199bf0dad6SMatthew G. Knepley       }
92209566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
92219566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
92229bf0dad6SMatthew G. Knepley     }
92233554e41dSMatthew G. Knepley   }
92243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9225552f7358SJed Brown }
92263913d7c8SMatthew G. Knepley 
9227bb6a34a8SMatthew G. Knepley /*@
9228bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
9229bb6a34a8SMatthew G. Knepley 
9230bb6a34a8SMatthew G. Knepley   Input Parameter:
9231a1cb98faSBarry Smith . dm - The `DMPLEX` object
9232a1cb98faSBarry Smith 
9233a1cb98faSBarry Smith   Level: developer
9234bb6a34a8SMatthew G. Knepley 
923595eb5ee5SVaclav Hapla   Notes:
923695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
923795eb5ee5SVaclav Hapla 
923820f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9239bb6a34a8SMatthew G. Knepley 
92401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9241bb6a34a8SMatthew G. Knepley @*/
9242d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
9243d71ae5a4SJacob Faibussowitsch {
9244a2a9e04cSMatthew G. Knepley   Vec       coordinates;
9245bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
9246bb6a34a8SMatthew G. Knepley   PetscReal vol;
924751a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
9248bb6a34a8SMatthew G. Knepley 
9249bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
92509566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
92519566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
92523ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
92539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
9254bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
92559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
9256a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
92579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
92583ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
9259412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9260412e9a14SMatthew G. Knepley     DMPolytopeType ct;
9261412e9a14SMatthew G. Knepley     PetscInt       unsplit;
9262412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
9263412e9a14SMatthew G. Knepley 
92649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
9265412e9a14SMatthew G. Knepley     switch (ct) {
9266412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
9267412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9268d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9269d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
9270d71ae5a4SJacob Faibussowitsch       break;
9271d71ae5a4SJacob Faibussowitsch     default:
9272d71ae5a4SJacob Faibussowitsch       break;
9273412e9a14SMatthew G. Knepley     }
9274412e9a14SMatthew G. Knepley     switch (ct) {
9275412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
9276412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9277412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9278d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
9279d71ae5a4SJacob Faibussowitsch       continue;
9280d71ae5a4SJacob Faibussowitsch     default:
9281d71ae5a4SJacob Faibussowitsch       break;
9282412e9a14SMatthew G. Knepley     }
92839566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9284412e9a14SMatthew G. Knepley     if (unsplit) continue;
92859566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
92861dca8a05SBarry 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);
928763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
92886858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
92896858538eSMatthew G. Knepley     if (depth > 1) {
92909566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
92911dca8a05SBarry 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);
929263a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9293bb6a34a8SMatthew G. Knepley     }
9294bb6a34a8SMatthew G. Knepley   }
92953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9296bb6a34a8SMatthew G. Knepley }
9297bb6a34a8SMatthew G. Knepley 
929803da9461SVaclav Hapla /*@
929920f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
93007726db96SVaclav Hapla 
930120f4b53cSBarry Smith   Collective
930203da9461SVaclav Hapla 
930303da9461SVaclav Hapla   Input Parameters:
9304a1cb98faSBarry Smith + dm              - The `DMPLEX` object
930520f4b53cSBarry Smith . pointSF         - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9306a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9307a1cb98faSBarry Smith 
9308a1cb98faSBarry Smith   Level: developer
930903da9461SVaclav Hapla 
9310e83a0d2dSVaclav Hapla   Notes:
9311e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
931203da9461SVaclav Hapla 
9313a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
931495eb5ee5SVaclav Hapla 
9315baca6076SPierre Jolivet   Extra roots can come from periodic cuts, where additional points appear on the boundary
9316d7d32a9aSMatthew G. Knepley 
93171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
931803da9461SVaclav Hapla @*/
9319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9320d71ae5a4SJacob Faibussowitsch {
93217726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
93227726db96SVaclav Hapla   const PetscInt    *locals;
93237726db96SVaclav Hapla   const PetscSFNode *remotes;
9324f0cfc026SVaclav Hapla   PetscBool          distributed;
93257726db96SVaclav Hapla   MPI_Comm           comm;
93267726db96SVaclav Hapla   PetscMPIInt        rank;
932703da9461SVaclav Hapla 
932803da9461SVaclav Hapla   PetscFunctionBegin;
932903da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93307726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
93317726db96SVaclav Hapla   else pointSF = dm->sf;
93327726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
93337726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
93347726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
93357726db96SVaclav Hapla   {
93367726db96SVaclav Hapla     PetscMPIInt mpiFlag;
93377726db96SVaclav Hapla 
93387726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
93397726db96SVaclav 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);
93407726db96SVaclav Hapla   }
93417726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
93429566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
93437726db96SVaclav Hapla   if (!distributed) {
93447726db96SVaclav 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);
93453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
93468918e3e2SVaclav Hapla   }
93477726db96SVaclav 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);
93487726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
934903da9461SVaclav Hapla 
93507726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
93517726db96SVaclav Hapla   {
93527726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
93537726db96SVaclav Hapla 
93547726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
93557726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9356d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
93577726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
93587726db96SVaclav Hapla   }
93597726db96SVaclav Hapla 
93607726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
93617726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
93627726db96SVaclav 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);
93637726db96SVaclav Hapla   }
93647726db96SVaclav Hapla 
93657726db96SVaclav Hapla   /* Check there are no cells in interface */
93667726db96SVaclav Hapla   if (!overlap) {
93677726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
93687726db96SVaclav Hapla 
93699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
93709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9371f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
93727726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9373f5869d18SMatthew G. Knepley 
93747726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
93757726db96SVaclav Hapla     }
937603da9461SVaclav Hapla   }
9377ece87651SVaclav Hapla 
93787726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
93797726db96SVaclav Hapla   {
93807726db96SVaclav Hapla     const PetscInt *rootdegree;
93817726db96SVaclav Hapla 
93827726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
93837726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9384f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
93857726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9386f5869d18SMatthew G. Knepley       const PetscInt *cone;
9387f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9388f5869d18SMatthew G. Knepley 
93899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
93909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9391f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9392f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
93937726db96SVaclav Hapla           if (locals) {
93949566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
93957726db96SVaclav Hapla           } else {
93967726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
93977726db96SVaclav Hapla           }
939863a3b9bcSJacob 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]);
9399f5869d18SMatthew G. Knepley         }
9400f5869d18SMatthew G. Knepley       }
9401ece87651SVaclav Hapla     }
94027726db96SVaclav Hapla   }
94033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
940403da9461SVaclav Hapla }
940503da9461SVaclav Hapla 
94067f9d8d6cSVaclav Hapla /*@
940720f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
94087f9d8d6cSVaclav Hapla 
94097f9d8d6cSVaclav Hapla   Input Parameter:
9410a1cb98faSBarry Smith . dm - The `DMPLEX` object
9411a1cb98faSBarry Smith 
9412a1cb98faSBarry Smith   Level: developer
94137f9d8d6cSVaclav Hapla 
94147f9d8d6cSVaclav Hapla   Notes:
94157f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
94167f9d8d6cSVaclav Hapla 
941720f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
94187f9d8d6cSVaclav Hapla 
941920f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
94207f9d8d6cSVaclav Hapla 
94211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
94227f9d8d6cSVaclav Hapla @*/
9423d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9424d71ae5a4SJacob Faibussowitsch {
94257f9d8d6cSVaclav Hapla   PetscInt cellHeight;
94267f9d8d6cSVaclav Hapla 
9427b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94287f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94299566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
94309566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
94319566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
94329566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9433d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
94349566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
94353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9436b5a892a1SMatthew G. Knepley }
9437b5a892a1SMatthew G. Knepley 
94389371c9d4SSatish Balay typedef struct cell_stats {
9439068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9440068a5610SStefano Zampini   PetscInt  count;
9441068a5610SStefano Zampini } cell_stats_t;
9442068a5610SStefano Zampini 
9443d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9444d71ae5a4SJacob Faibussowitsch {
9445068a5610SStefano Zampini   PetscInt i, N = *len;
9446068a5610SStefano Zampini 
9447068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9448068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9449068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9450068a5610SStefano Zampini 
9451068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9452068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9453068a5610SStefano Zampini     B->sum += A->sum;
9454068a5610SStefano Zampini     B->squaresum += A->squaresum;
9455068a5610SStefano Zampini     B->count += A->count;
9456068a5610SStefano Zampini   }
9457068a5610SStefano Zampini }
9458068a5610SStefano Zampini 
9459068a5610SStefano Zampini /*@
946043fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9461068a5610SStefano Zampini 
946220f4b53cSBarry Smith   Collective
94638261a58bSMatthew G. Knepley 
9464068a5610SStefano Zampini   Input Parameters:
9465a1cb98faSBarry Smith + dm        - The `DMPLEX` object
946620f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9467a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9468a1cb98faSBarry Smith 
9469a1cb98faSBarry Smith   Level: developer
9470068a5610SStefano Zampini 
947195eb5ee5SVaclav Hapla   Notes:
947295eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
947395eb5ee5SVaclav Hapla 
9474a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9475068a5610SStefano Zampini 
94761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9477068a5610SStefano Zampini @*/
9478d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9479d71ae5a4SJacob Faibussowitsch {
9480068a5610SStefano Zampini   DM           dmCoarse;
948143fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
948243fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
948343fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
948443fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9485412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
948643fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9487068a5610SStefano Zampini 
9488068a5610SStefano Zampini   PetscFunctionBegin;
9489068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9490068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9491068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9492068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9493068a5610SStefano Zampini   stats.count                 = 0;
9494068a5610SStefano Zampini 
94959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
94969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
94979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
94989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
94999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
95009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9501412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9502068a5610SStefano Zampini     PetscInt  i;
9503068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9504068a5610SStefano Zampini 
95059566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
950663a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
950743fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9508068a5610SStefano Zampini       frobJ += J[i] * J[i];
9509068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9510068a5610SStefano Zampini     }
9511068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9512068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9513068a5610SStefano Zampini 
9514068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9515068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9516068a5610SStefano Zampini     stats.sum += cond;
9517068a5610SStefano Zampini     stats.squaresum += cond2;
9518068a5610SStefano Zampini     stats.count++;
95198261a58bSMatthew G. Knepley     if (output && cond > limit) {
952043fa8764SMatthew G. Knepley       PetscSection coordSection;
952143fa8764SMatthew G. Knepley       Vec          coordsLocal;
952243fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
952343fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
952443fa8764SMatthew G. Knepley 
95259566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
95269566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
95279566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
952863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
952943fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
953063a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
953143fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
95329566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
95339566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
953443fa8764SMatthew G. Knepley         }
95359566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
953643fa8764SMatthew G. Knepley       }
95379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
953843fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
953943fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
954043fa8764SMatthew G. Knepley 
954143fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
954243fa8764SMatthew G. Knepley           PetscReal len;
954343fa8764SMatthew G. Knepley 
95449566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
954563a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
954643fa8764SMatthew G. Knepley         }
954743fa8764SMatthew G. Knepley       }
95489566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
95499566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
955043fa8764SMatthew G. Knepley     }
9551068a5610SStefano Zampini   }
95529566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9553068a5610SStefano Zampini 
9554068a5610SStefano Zampini   if (size > 1) {
9555068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9556068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9557068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9558068a5610SStefano Zampini     MPI_Op       statReduce;
9559068a5610SStefano Zampini 
95609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
95619566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
95629566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
95639566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
95649566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
95659566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9566068a5610SStefano Zampini   } else {
95679566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9568068a5610SStefano Zampini   }
9569dd400576SPatrick Sanan   if (rank == 0) {
9570068a5610SStefano Zampini     count = globalStats.count;
9571068a5610SStefano Zampini     min   = globalStats.min;
9572068a5610SStefano Zampini     max   = globalStats.max;
9573068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9574068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9575068a5610SStefano Zampini   }
9576068a5610SStefano Zampini 
957748a46eb9SPierre 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));
95789566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9579068a5610SStefano Zampini 
95809566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9581068a5610SStefano Zampini   if (dmCoarse) {
9582068a5610SStefano Zampini     PetscBool isplex;
9583068a5610SStefano Zampini 
95849566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
95851baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9586068a5610SStefano Zampini   }
95873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9588068a5610SStefano Zampini }
9589068a5610SStefano Zampini 
9590f108dbd7SJacob Faibussowitsch /*@
9591f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9592f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9593f108dbd7SJacob Faibussowitsch 
959420f4b53cSBarry Smith   Collective
9595f108dbd7SJacob Faibussowitsch 
9596f108dbd7SJacob Faibussowitsch   Input Parameters:
9597a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9598a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9599f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9600f108dbd7SJacob Faibussowitsch 
9601f108dbd7SJacob Faibussowitsch   Output Parameters:
960220f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9603a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9604f108dbd7SJacob Faibussowitsch 
9605f108dbd7SJacob Faibussowitsch   Options Database Keys:
9606a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9607f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view   - view OrthQual vector.
9608f108dbd7SJacob Faibussowitsch 
9609a1cb98faSBarry Smith   Level: intermediate
9610a1cb98faSBarry Smith 
9611f108dbd7SJacob Faibussowitsch   Notes:
9612a4e35b19SJacob Faibussowitsch   Orthogonal quality is given by the following formula\:
9613f108dbd7SJacob Faibussowitsch 
9614a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9615f108dbd7SJacob Faibussowitsch 
9616f108dbd7SJacob 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
9617f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9618f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9619f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9620f108dbd7SJacob Faibussowitsch 
9621f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9622f108dbd7SJacob Faibussowitsch 
9623a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9624f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9625f108dbd7SJacob Faibussowitsch 
9626f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9627f108dbd7SJacob Faibussowitsch 
96281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9629f108dbd7SJacob Faibussowitsch @*/
9630d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9631d71ae5a4SJacob Faibussowitsch {
96326ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
96336ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
96346ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9635f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
96366ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9637f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9638f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9639f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9640f108dbd7SJacob Faibussowitsch   IS                     glob;
9641f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9642f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9643f108dbd7SJacob Faibussowitsch 
9644f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9645f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9646ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
96474f572ea9SToby Isaac   PetscAssertPointer(OrthQual, 4);
96486bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
96499566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
96509566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
965163a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
96526ed19f2fSJacob Faibussowitsch   {
96536ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
96546ed19f2fSJacob Faibussowitsch 
96559566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9656f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9657f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9658f108dbd7SJacob Faibussowitsch 
96599566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
966098921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9661f108dbd7SJacob Faibussowitsch     }
96626ed19f2fSJacob Faibussowitsch   }
9663f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
96644f572ea9SToby Isaac     PetscAssertPointer(OrthQualLabel, 5);
96659566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
96669566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
96679371c9d4SSatish Balay   } else {
96689371c9d4SSatish Balay     *OrthQualLabel = NULL;
96699371c9d4SSatish Balay   }
96709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
96719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
96729566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
96739566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
96749566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
96759566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
96769566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
96779566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
96789566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
96799566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
96809566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
96819566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
96829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
96839566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
96849566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
96859566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
96869566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
96879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
96886ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
96896ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9690f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9691f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9692898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9693f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9694f108dbd7SJacob Faibussowitsch 
96956ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9696f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9697f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
96989566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
96999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9700f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
97019566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
97026ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
97036ed19f2fSJacob Faibussowitsch       PetscInt         i;
97046ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9705f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9706f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9707f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9708f108dbd7SJacob Faibussowitsch 
9709f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9710f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
97119566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9712f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
97136ed19f2fSJacob Faibussowitsch       {
97146ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
97156ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
97166ed19f2fSJacob Faibussowitsch 
97179566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
97189566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
97199566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
97206ed19f2fSJacob Faibussowitsch       }
9721f108dbd7SJacob Faibussowitsch 
9722f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9723f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9724f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9725f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9726f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9727addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9728addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9729addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9730f108dbd7SJacob Faibussowitsch       }
9731addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9732addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9733addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9734f108dbd7SJacob Faibussowitsch 
9735f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9736f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9737f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9738f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9739f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9740f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9741f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9742f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9743f108dbd7SJacob Faibussowitsch       }
9744ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9745ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9746f108dbd7SJacob Faibussowitsch     }
97479566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
97489566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9749f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
97506ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9751f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
97529566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9753f108dbd7SJacob Faibussowitsch     }
9754f108dbd7SJacob Faibussowitsch   }
97559566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
97569566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
97579566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
97589566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
97599566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
97609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9761f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
97629566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9763f108dbd7SJacob Faibussowitsch   }
97649566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
9765cd791dc2SBarry Smith   PetscCall(PetscOptionsRestoreViewer(&vwr));
97669566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
97673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9768f108dbd7SJacob Faibussowitsch }
9769f108dbd7SJacob Faibussowitsch 
9770d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
97711eb70e55SToby Isaac  * interpolator construction */
9772d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9773d71ae5a4SJacob Faibussowitsch {
97741eb70e55SToby Isaac   PetscSection section, newSection, gsection;
97751eb70e55SToby Isaac   PetscSF      sf;
97761eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
97771eb70e55SToby Isaac 
97781eb70e55SToby Isaac   PetscFunctionBegin;
97791eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97804f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
97819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
97829566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9783712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
97841eb70e55SToby Isaac   if (!ghasConstraints) {
97859566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
97861eb70e55SToby Isaac     *odm = dm;
97873ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
97881eb70e55SToby Isaac   }
97899566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
97909566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
97919566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
97929566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
9793eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection));
97949566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
97959566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
97963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97971eb70e55SToby Isaac }
97981eb70e55SToby Isaac 
9799d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9800d71ae5a4SJacob Faibussowitsch {
98011eb70e55SToby Isaac   DM        dmco, dmfo;
98021eb70e55SToby Isaac   Mat       interpo;
98031eb70e55SToby Isaac   Vec       rscale;
98041eb70e55SToby Isaac   Vec       cglobalo, clocal;
98051eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
98061eb70e55SToby Isaac   PetscBool regular;
98071eb70e55SToby Isaac 
98081eb70e55SToby Isaac   PetscFunctionBegin;
98099566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
98109566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
98119566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
98129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
98139566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
98149566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
98159566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
98169566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
98179566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
98189566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
98199566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
98209566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
98219566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
98229566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
98239566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
98249566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
98259566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
98269566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
98279566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
98289566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
98299566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
98309566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
98319566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
98329566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
98331eb70e55SToby Isaac   *shift = fglobal;
98349566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
98359566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
98369566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
98379566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
98389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
98399566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
98409566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
98419566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
98423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98431eb70e55SToby Isaac }
98441eb70e55SToby Isaac 
9845d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9846d71ae5a4SJacob Faibussowitsch {
98471eb70e55SToby Isaac   PetscObject shifto;
98481eb70e55SToby Isaac   Vec         shift;
98491eb70e55SToby Isaac 
98501eb70e55SToby Isaac   PetscFunctionBegin;
98511eb70e55SToby Isaac   if (!interp) {
98521eb70e55SToby Isaac     Vec rscale;
98531eb70e55SToby Isaac 
98549566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
98559566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
98561eb70e55SToby Isaac   } else {
98579566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
98581eb70e55SToby Isaac   }
98599566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
98601eb70e55SToby Isaac   if (!shifto) {
98619566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
98629566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
98631eb70e55SToby Isaac     shifto = (PetscObject)shift;
98649566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
98651eb70e55SToby Isaac   }
98661eb70e55SToby Isaac   shift = (Vec)shifto;
98679566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
98689566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
98699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
98703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98711eb70e55SToby Isaac }
98721eb70e55SToby Isaac 
9873bceba477SMatthew G. Knepley /* Pointwise interpolation
9874bceba477SMatthew G. Knepley      Just code FEM for now
9875bceba477SMatthew G. Knepley      u^f = I u^c
98764ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
98774ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
98784ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9879bceba477SMatthew G. Knepley */
9880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9881d71ae5a4SJacob Faibussowitsch {
9882bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9883bceba477SMatthew G. Knepley   PetscInt     m, n;
9884a063dac3SMatthew G. Knepley   void        *ctx;
988568132eb9SMatthew G. Knepley   DM           cdm;
9886cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9887bceba477SMatthew G. Knepley 
9888bceba477SMatthew G. Knepley   PetscFunctionBegin;
98899566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
98909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
98919566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
98929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
989368132eb9SMatthew G. Knepley 
98949566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
98959566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
98969566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
98979566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
98989566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
989968132eb9SMatthew G. Knepley 
99009566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
99019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
99029566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
99039566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
99049566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
99054db47ee9SStefano Zampini   if (scaling) {
99065d1c2e58SMatthew G. Knepley     /* Use naive scaling */
99079566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
99084db47ee9SStefano Zampini   }
99093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9910a063dac3SMatthew G. Knepley }
9911bceba477SMatthew G. Knepley 
9912d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9913d71ae5a4SJacob Faibussowitsch {
99146dbf9973SLawrence Mitchell   VecScatter ctx;
991590748bafSMatthew G. Knepley 
9916a063dac3SMatthew G. Knepley   PetscFunctionBegin;
99179566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
99189566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
99199566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
99203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9921bceba477SMatthew G. Knepley }
9922bceba477SMatthew G. Knepley 
9923d71ae5a4SJacob 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[])
9924d71ae5a4SJacob Faibussowitsch {
992500635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
992600635df3SMatthew G. Knepley   PetscInt       c;
992700635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
99283e9753d6SMatthew G. Knepley }
99293e9753d6SMatthew G. Knepley 
9930d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9931d71ae5a4SJacob Faibussowitsch {
9932b4937a87SMatthew G. Knepley   DM           dmc;
9933b4937a87SMatthew G. Knepley   PetscDS      ds;
9934b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9935b4937a87SMatthew G. Knepley   IS           cellIS;
9936b4937a87SMatthew G. Knepley   PetscFormKey key;
9937b4937a87SMatthew G. Knepley   PetscInt     depth;
9938b4937a87SMatthew G. Knepley 
9939b4937a87SMatthew G. Knepley   PetscFunctionBegin;
99409566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
99419566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
99429566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
99439566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
99449566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
99459566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
99469566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
99479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
99489566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
99499566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
99509566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9951b4937a87SMatthew G. Knepley   key.label = NULL;
9952b4937a87SMatthew G. Knepley   key.value = 0;
9953b4937a87SMatthew G. Knepley   key.field = 0;
9954b4937a87SMatthew G. Knepley   key.part  = 0;
99559566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
99569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
99579566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
99589566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
99599566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
99609566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
99619566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
99629566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
99633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9964b4937a87SMatthew G. Knepley }
9965b4937a87SMatthew G. Knepley 
9966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9967d71ae5a4SJacob Faibussowitsch {
9968bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9969bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9970bd041c0cSMatthew G. Knepley   void        *ctx;
9971bd041c0cSMatthew G. Knepley   DM           cdm;
9972bd041c0cSMatthew G. Knepley   PetscBool    regular;
9973bd041c0cSMatthew G. Knepley 
9974bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
99753e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
99763e9753d6SMatthew G. Knepley     DM            dmc;
99773e9753d6SMatthew G. Knepley     PetscDS       ds;
9978b4937a87SMatthew G. Knepley     PetscWeakForm wf;
99793e9753d6SMatthew G. Knepley     Vec           u;
99803e9753d6SMatthew G. Knepley     IS            cellIS;
998106ad1575SMatthew G. Knepley     PetscFormKey  key;
99823e9753d6SMatthew G. Knepley     PetscInt      depth;
99833e9753d6SMatthew G. Knepley 
99849566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
99859566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
99869566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
99879566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
99889566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
99899566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
99909566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
99918d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
99929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
99939566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
99949566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
99956528b96dSMatthew G. Knepley     key.label = NULL;
99966528b96dSMatthew G. Knepley     key.value = 0;
99976528b96dSMatthew G. Knepley     key.field = 0;
999806ad1575SMatthew G. Knepley     key.part  = 0;
99999566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
100009566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
100018d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
100029566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
100033e9753d6SMatthew G. Knepley   } else {
100049566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
100059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
100069566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
100079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
10008bd041c0cSMatthew G. Knepley 
100099566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
100109566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
100119566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
100129566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
10013bd041c0cSMatthew G. Knepley 
100149566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
100159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
100169566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
100179566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
100183e9753d6SMatthew G. Knepley   }
100199566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
100203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10021bd041c0cSMatthew G. Knepley }
10022bd041c0cSMatthew G. Knepley 
100230aef6b92SMatthew G. Knepley /*@
100240aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
100250aef6b92SMatthew G. Knepley 
100260aef6b92SMatthew G. Knepley   Input Parameter:
10027a1cb98faSBarry Smith . dm - The `DMPLEX` object
100280aef6b92SMatthew G. Knepley 
100290aef6b92SMatthew G. Knepley   Output Parameter:
100300aef6b92SMatthew G. Knepley . regular - The flag
100310aef6b92SMatthew G. Knepley 
100320aef6b92SMatthew G. Knepley   Level: intermediate
100330aef6b92SMatthew G. Knepley 
100341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
100350aef6b92SMatthew G. Knepley @*/
10036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
10037d71ae5a4SJacob Faibussowitsch {
100380aef6b92SMatthew G. Knepley   PetscFunctionBegin;
100390aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100404f572ea9SToby Isaac   PetscAssertPointer(regular, 2);
100410aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
100423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
100430aef6b92SMatthew G. Knepley }
100440aef6b92SMatthew G. Knepley 
100450aef6b92SMatthew G. Knepley /*@
100460aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
100470aef6b92SMatthew G. Knepley 
100480aef6b92SMatthew G. Knepley   Input Parameters:
10049a1cb98faSBarry Smith + dm      - The `DMPLEX` object
100500aef6b92SMatthew G. Knepley - regular - The flag
100510aef6b92SMatthew G. Knepley 
100520aef6b92SMatthew G. Knepley   Level: intermediate
100530aef6b92SMatthew G. Knepley 
100541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
100550aef6b92SMatthew G. Knepley @*/
10056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
10057d71ae5a4SJacob Faibussowitsch {
100580aef6b92SMatthew G. Knepley   PetscFunctionBegin;
100590aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100600aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
100613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
100620aef6b92SMatthew G. Knepley }
100630aef6b92SMatthew G. Knepley 
10064a68b90caSToby Isaac /*@
10065f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
10066a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
10067a68b90caSToby Isaac 
10068a1cb98faSBarry Smith   Not Collective
10069a68b90caSToby Isaac 
10070f899ff85SJose E. Roman   Input Parameter:
10071a1cb98faSBarry Smith . dm - The `DMPLEX` object
10072a68b90caSToby Isaac 
10073a68b90caSToby Isaac   Output Parameters:
1007420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
1007520f4b53cSBarry Smith - anchorIS      - If not `NULL`, set to the list of anchors indexed by `anchorSection`
10076a68b90caSToby Isaac 
10077a68b90caSToby Isaac   Level: intermediate
10078a68b90caSToby Isaac 
100791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
10080a68b90caSToby Isaac @*/
10081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
10082d71ae5a4SJacob Faibussowitsch {
10083a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
10084a68b90caSToby Isaac 
10085a68b90caSToby Isaac   PetscFunctionBegin;
10086a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100879566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
10088a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
10089a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
100903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10091a68b90caSToby Isaac }
10092a68b90caSToby Isaac 
10093a68b90caSToby Isaac /*@
10094a4e35b19SJacob Faibussowitsch   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.
10095a68b90caSToby Isaac 
1009620f4b53cSBarry Smith   Collective
10097a68b90caSToby Isaac 
10098a68b90caSToby Isaac   Input Parameters:
10099a1cb98faSBarry Smith + dm            - The `DMPLEX` object
10100a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
10101a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10102a1cb98faSBarry Smith - anchorIS      - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10103a68b90caSToby Isaac 
10104a68b90caSToby Isaac   Level: intermediate
10105a68b90caSToby Isaac 
10106a1cb98faSBarry Smith   Notes:
10107a4e35b19SJacob Faibussowitsch   Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to
10108a4e35b19SJacob Faibussowitsch   an outside value, the anchor constraints set a point's degrees of freedom to be a linear
10109a4e35b19SJacob Faibussowitsch   combination of other points' degrees of freedom.
10110a4e35b19SJacob Faibussowitsch 
10111a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
10112a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
10113a1cb98faSBarry Smith 
1011420f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
10115a1cb98faSBarry Smith 
101161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
10117a68b90caSToby Isaac @*/
10118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
10119d71ae5a4SJacob Faibussowitsch {
10120a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
10121e228b242SToby Isaac   PetscMPIInt result;
10122a68b90caSToby Isaac 
10123a68b90caSToby Isaac   PetscFunctionBegin;
10124a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10125e228b242SToby Isaac   if (anchorSection) {
10126e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
101279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
101281dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
10129e228b242SToby Isaac   }
10130e228b242SToby Isaac   if (anchorIS) {
10131e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
101329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
101331dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
10134e228b242SToby Isaac   }
10135a68b90caSToby Isaac 
101369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
101379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
10138a68b90caSToby Isaac   plex->anchorSection = anchorSection;
10139a68b90caSToby Isaac 
101409566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
101419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
10142a68b90caSToby Isaac   plex->anchorIS = anchorIS;
10143a68b90caSToby Isaac 
10144cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
10145a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
10146a68b90caSToby Isaac     const PetscInt *anchors;
10147a68b90caSToby Isaac 
101489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
101499566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
101509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
10151a68b90caSToby Isaac     for (a = 0; a < size; a++) {
10152a68b90caSToby Isaac       PetscInt p;
10153a68b90caSToby Isaac 
10154a68b90caSToby Isaac       p = anchors[a];
10155a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
10156a68b90caSToby Isaac         PetscInt dof;
10157a68b90caSToby Isaac 
101589566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10159a68b90caSToby Isaac         if (dof) {
101609566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
1016163a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
10162a68b90caSToby Isaac         }
10163a68b90caSToby Isaac       }
10164a68b90caSToby Isaac     }
101659566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
10166a68b90caSToby Isaac   }
10167f7c74593SToby Isaac   /* reset the generic constraints */
101689566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
101693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10170a68b90caSToby Isaac }
10171a68b90caSToby Isaac 
10172d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
10173d71ae5a4SJacob Faibussowitsch {
10174f7c74593SToby Isaac   PetscSection anchorSection;
101756995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
10176a68b90caSToby Isaac 
10177a68b90caSToby Isaac   PetscFunctionBegin;
10178a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
101809566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
101819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
101826995de1eSToby Isaac   if (numFields) {
10183719ab38cSToby Isaac     PetscInt f;
101849566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
10185719ab38cSToby Isaac 
10186719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
10187719ab38cSToby Isaac       PetscInt numComp;
10188719ab38cSToby Isaac 
101899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
101909566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
10191719ab38cSToby Isaac     }
101926995de1eSToby Isaac   }
101939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
101949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
101956995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
101966995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
101976995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
101989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
10199a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
102009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10201a68b90caSToby Isaac     if (dof) {
102029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
102039566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
10204a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
102059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
102069566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
10207a68b90caSToby Isaac       }
10208a68b90caSToby Isaac     }
10209a68b90caSToby Isaac   }
102109566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
102119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
102123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10213a68b90caSToby Isaac }
10214a68b90caSToby Isaac 
10215d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
10216d71ae5a4SJacob Faibussowitsch {
10217f7c74593SToby Isaac   PetscSection    aSec;
10218ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
102190ac89760SToby Isaac   const PetscInt *anchors;
102200ac89760SToby Isaac   PetscInt        numFields, f;
1022166ad2231SToby Isaac   IS              aIS;
10222e19f7ee6SMark Adams   MatType         mtype;
10223e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
102240ac89760SToby Isaac 
102250ac89760SToby Isaac   PetscFunctionBegin;
102260ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
102289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
102299566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
102309566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
102319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
102329566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
102339566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
102349566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
10235e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
10236e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
10237e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
102389566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
102399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
102409566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
102416995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
102429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
102439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
102449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
102450ac89760SToby Isaac   i[0] = 0;
102469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
102470ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
10248f19733c5SToby Isaac     PetscInt rDof, rOff, r;
10249f19733c5SToby Isaac 
102509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
10251f19733c5SToby Isaac     if (!rDof) continue;
102529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
102530ac89760SToby Isaac     if (numFields) {
102540ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
102550ac89760SToby Isaac         annz = 0;
10256f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
10257f19733c5SToby Isaac           a = anchors[rOff + r];
10258ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
102599566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
102600ac89760SToby Isaac           annz += aDof;
102610ac89760SToby Isaac         }
102629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
102639566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
10264ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
102650ac89760SToby Isaac       }
102662f7452b8SBarry Smith     } else {
102670ac89760SToby Isaac       annz = 0;
102689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
102690ac89760SToby Isaac       for (q = 0; q < dof; q++) {
10270ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
10271ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
102729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
102730ac89760SToby Isaac         annz += aDof;
102740ac89760SToby Isaac       }
102759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
102769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
10277ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
102780ac89760SToby Isaac     }
102790ac89760SToby Isaac   }
102800ac89760SToby Isaac   nnz = i[m];
102819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
102820ac89760SToby Isaac   offset = 0;
102830ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
102840ac89760SToby Isaac     if (numFields) {
102850ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
102869566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
102870ac89760SToby Isaac         for (q = 0; q < dof; q++) {
102880ac89760SToby Isaac           PetscInt rDof, rOff, r;
102899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
102909566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
102910ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
102920ac89760SToby Isaac             PetscInt s;
102930ac89760SToby Isaac 
102940ac89760SToby Isaac             a = anchors[rOff + r];
10295ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
102969566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
102979566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10298ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
102990ac89760SToby Isaac           }
103000ac89760SToby Isaac         }
103010ac89760SToby Isaac       }
103022f7452b8SBarry Smith     } else {
103039566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103040ac89760SToby Isaac       for (q = 0; q < dof; q++) {
103050ac89760SToby Isaac         PetscInt rDof, rOff, r;
103069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
103079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103080ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
103090ac89760SToby Isaac           PetscInt s;
103100ac89760SToby Isaac 
103110ac89760SToby Isaac           a = anchors[rOff + r];
10312ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
103139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
103149566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10315ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
103160ac89760SToby Isaac         }
103170ac89760SToby Isaac       }
103180ac89760SToby Isaac     }
103190ac89760SToby Isaac   }
103209566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
103219566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
103229566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
103239566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
103243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103250ac89760SToby Isaac }
103260ac89760SToby Isaac 
10327d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10328d71ae5a4SJacob Faibussowitsch {
10329f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10330f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1033166ad2231SToby Isaac   Mat          cMat;
1033266ad2231SToby Isaac 
1033366ad2231SToby Isaac   PetscFunctionBegin;
1033466ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
103359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1033666ad2231SToby Isaac   if (anchorSection) {
1033744a7f3ddSMatthew G. Knepley     PetscInt Nf;
10338e228b242SToby Isaac 
103399566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
103409566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
103419566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
103429566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
103439566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
103449566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
103459566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
103469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1034766ad2231SToby Isaac   }
103483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1034966ad2231SToby Isaac }
10350a93c429eSMatthew G. Knepley 
10351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10352d71ae5a4SJacob Faibussowitsch {
10353a93c429eSMatthew G. Knepley   IS           subis;
10354a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10355a93c429eSMatthew G. Knepley 
10356a93c429eSMatthew G. Knepley   PetscFunctionBegin;
103579566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1035828b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1035928b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10360a93c429eSMatthew G. Knepley   /* Create subdomain */
1036130cbcd5dSksagiyam   PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, NULL, subdm));
10362a93c429eSMatthew G. Knepley   /* Create submodel */
103639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
103649566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
103659566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
103669566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
103679566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10368a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10369a93c429eSMatthew G. Knepley   if (is) {
10370a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10371a93c429eSMatthew G. Knepley     IS              spIS;
10372a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10373a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10374a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10375a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10376a93c429eSMatthew G. Knepley 
103779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
103789566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
103799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
103809566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
103819566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
103829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10383a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10384a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10385a93c429eSMatthew G. Knepley 
103869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10387a93c429eSMatthew G. Knepley       if (gdof > 0) {
10388a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10389a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10390a93c429eSMatthew G. Knepley 
103919566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
103929566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10393a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10394a93c429eSMatthew G. Knepley         }
10395a93c429eSMatthew G. Knepley         subSize += pSubSize;
10396a93c429eSMatthew G. Knepley         if (pSubSize) {
10397a93c429eSMatthew G. Knepley           if (bs < 0) {
10398a93c429eSMatthew G. Knepley             bs = pSubSize;
10399a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10400a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10401a93c429eSMatthew G. Knepley             bs = 1;
10402a93c429eSMatthew G. Knepley           }
10403a93c429eSMatthew G. Knepley         }
10404a93c429eSMatthew G. Knepley       }
10405a93c429eSMatthew G. Knepley     }
10406a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
104079371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
104089371c9d4SSatish Balay     bsLocal[1] = bs;
104099566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
104109371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
104119371c9d4SSatish Balay       bs = 1;
104129371c9d4SSatish Balay     } else {
104139371c9d4SSatish Balay       bs = bsMinMax[0];
104149371c9d4SSatish Balay     }
104159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10416a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10417a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10418a93c429eSMatthew G. Knepley 
104199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10420a93c429eSMatthew G. Knepley       if (gdof > 0) {
10421a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10422a93c429eSMatthew G. Knepley 
104239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10424a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10425a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10426a93c429eSMatthew G. Knepley 
10427a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10428a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
104299566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
104309566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10431a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10432a93c429eSMatthew G. Knepley           }
104339566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
104349566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10435ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10436a93c429eSMatthew G. Knepley         }
10437a93c429eSMatthew G. Knepley       }
10438a93c429eSMatthew G. Knepley     }
104399566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
104409566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10441a93c429eSMatthew G. Knepley     if (bs > 1) {
10442a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10443a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10444a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10445a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
104469371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
104479371c9d4SSatish Balay             set = 0;
104489371c9d4SSatish Balay             break;
104499371c9d4SSatish Balay           }
10450a93c429eSMatthew G. Knepley         }
10451a93c429eSMatthew G. Knepley       }
104529566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10453a93c429eSMatthew G. Knepley     }
10454a93c429eSMatthew G. Knepley     /* Attach nullspace */
10455a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10456a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10457a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10458a93c429eSMatthew G. Knepley     }
10459a93c429eSMatthew G. Knepley     if (f < Nf) {
10460a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
104619566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
104626823f3c5SBlaise Bourdin 
104639566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
104649566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10465a93c429eSMatthew G. Knepley     }
10466a93c429eSMatthew G. Knepley   }
104673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10468a93c429eSMatthew G. Knepley }
10469c0f0dcc3SMatthew G. Knepley 
10470c0f0dcc3SMatthew G. Knepley /*@
10471c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10472c0f0dcc3SMatthew G. Knepley 
10473a1cb98faSBarry Smith   Input Parameters:
10474a1cb98faSBarry Smith + dm    - The `DM`
10475a1cb98faSBarry Smith - dummy - unused argument
10476a1cb98faSBarry Smith 
10477a1cb98faSBarry Smith   Options Database Key:
10478a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10479c0f0dcc3SMatthew G. Knepley 
10480c0f0dcc3SMatthew G. Knepley   Level: developer
10481c0f0dcc3SMatthew G. Knepley 
104821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10483c0f0dcc3SMatthew G. Knepley @*/
10484d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10485d71ae5a4SJacob Faibussowitsch {
10486b665b14eSToby Isaac   PetscLogHandler default_handler;
10487b665b14eSToby Isaac 
104882611ad71SToby Isaac   PetscFunctionBegin;
104892611ad71SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10490b665b14eSToby Isaac   PetscCall(PetscLogGetDefaultHandler(&default_handler));
10491b665b14eSToby Isaac   if (default_handler) {
10492c0f0dcc3SMatthew G. Knepley     PetscLogEvent      event;
10493c0f0dcc3SMatthew G. Knepley     PetscEventPerfInfo eventInfo;
10494c0f0dcc3SMatthew G. Knepley     PetscReal          cellRate, flopRate;
10495c0f0dcc3SMatthew G. Knepley     PetscInt           cStart, cEnd, Nf, N;
10496c0f0dcc3SMatthew G. Knepley     const char        *name;
10497c0f0dcc3SMatthew G. Knepley 
104989566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
104999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
105009566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
105019566063dSJacob Faibussowitsch     PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
10502b665b14eSToby Isaac     PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo));
10503c0f0dcc3SMatthew G. Knepley     N        = (cEnd - cStart) * Nf * eventInfo.count;
10504c0f0dcc3SMatthew G. Knepley     flopRate = eventInfo.flops / eventInfo.time;
10505c0f0dcc3SMatthew G. Knepley     cellRate = N / eventInfo.time;
1050663a3b9bcSJacob 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)));
105072611ad71SToby Isaac   } else {
10508b665b14eSToby 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.");
105092611ad71SToby Isaac   }
105103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10511c0f0dcc3SMatthew G. Knepley }
10512